1446 Commits

Author SHA1 Message Date
cd466ebdd4 Update ChangeLog and configure.ac for 1.90 (#1739)
Fixes #1737.
2021-08-08 14:01:19 +09:00
15e89b78de Add a partial page_list unit test (#1735) 2021-08-04 07:36:32 +09:00
66006ba48d Add dedicated upper- and lower-case hex functions (#1734)
This makes the call sites more readable than a boolean parameter.
2021-08-04 07:28:51 +09:00
18e9c62087 Make string constants read-only const (#1733)
This removes some global constructors.  Also use a consistent ALL_CAPS
style.
2021-08-03 00:10:27 +09:00
34f89e5936 Added fake_diskfree option to deceive free disk space for test 2021-08-02 11:04:42 +09:00
e1f3b9d8c1 Add support for AWS-style environment variables (#1729)
Support AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN
in addition to the AWSACCESSKEYID, AWSSECRETACCESSKEY and
AWSSESSIONTOKEN.

The old environment variables are still supported, but they are
deprecated and no longer documented.

Close #1708
2021-07-26 23:29:45 +09:00
d3278f4886 Loosen CheckBucket to check only the bucket (#1728)
Previously it checked if there was an object present, assuming that
this was a directory object normally created for s3fs directories.
However most S3 clients do not create this object for virtual folders.
Fixes #1460.  Fixes #1687.
2021-07-25 12:29:00 +09:00
77f0b75d2f Add jitter to avoid thundering herd (#1723) 2021-07-25 10:22:19 +09:00
012e6dd8a2 Fix README nit (#1726) 2021-07-22 13:54:20 +09:00
199b3d4709 Fixed a bug in disk free space calculation 2021-07-18 14:52:11 +09:00
7890989cbb Address cppcheck 2.5 warnings (#1720)
This slightly simplifies memory management.
2021-07-14 22:18:09 +09:00
945cc2ac54 Added UntreatedParts class instead of untreated upload info members in PseudoFdInfo 2021-07-12 21:45:29 +09:00
c30acbbf90 Splited some methods of FdEntity class by uploading mode
- Splited FdEntity::Write method by uploading mode
- Splited FdEntity::RowFlush method by uplading mode
2021-07-10 17:24:34 +09:00
881025cc9e Add initiator pid, uid and gid to a debug log (#1716) 2021-07-10 16:23:20 +09:00
4cc210c5ab Prevents the etag string buffer from being destroyed during use
and absorbed MPPART_INFO structure into filepart structure
2021-07-03 22:42:18 +09:00
2d5316a334 Fixed 1710 - Added a flag for check in Linux 2021-07-02 11:34:51 +09:00
9cfa177af0 Add flag to run all tests (#1710)
This allows CI to run the full set of tests while making local
development faster.
2021-07-02 08:41:47 +09:00
fe44355d25 Report s3fs space as 18.4 EB (#1709)
256 TB probably seemed large in 2007 but in 2021 it is small enough to
confuse some users.
2021-07-02 07:56:05 +09:00
487df27008 Return EREMOTE when reading Glacier objects (#1705)
Previously s3fs returned EIO which was not helpful to the caller.
Returning a more specific error code allows automatically restoring
the object via RestoreObject in a subsequent commit.
References #1466.
2021-06-30 09:25:36 +09:00
1965916f7a Convert storage class values to uppercase (#1704)
AWS requires uppercase values.  Fixes a regression from
bbcccd6e98.  References #1613.
2021-06-30 09:03:31 +09:00
8948eded09 Address clang-tidy warnings (#1703) 2021-06-30 08:42:44 +09:00
2f59cb5a0a Remove unneeded volatile qualifiers (#1702)
We should use proper locking instead.  Specifically for
is_meta_pending this does not do what was intended due to the
read-modify-write of the member.
2021-06-30 08:20:44 +09:00
f505c8224e Explicitly specify lock type (#1701)
This makes it more clear and type-safe if the caller already has the
lock.  Follows on to 84174c560d.
2021-06-27 15:15:48 +09:00
2154e898bc Fix typos (#1700) 2021-06-27 11:22:33 +09:00
f9e80f995d Fixed a bug about rename existing file of different sizes by mpcopy 2021-06-26 00:04:58 +09:00
a5c1915772 Set CURLOPT_UNRESTRICTED_AUTH when authenticating (#1681)
This is necessary for authentication to work with AWS when it responds with 307 to the check bucket request when mounting. This happens to newly created buckets according to https://aws.amazon.com/premiumsupport/knowledge-center/s3-http-307-response/.

Prior to this, curl would follow the redirect, but would not include the `Authorization` header which would end up with `404`.

Co-authored-by: Takeshi Nakatani <ggtakec@gmail.com>
2021-06-25 20:26:12 +09:00
6edf3d6427 Updated to clearly output message about the file descriptor type(pseudo/physical) 2021-06-25 19:18:08 +09:00
944c1fd148 Clean up litter in ut_test (#1697) 2021-06-25 19:15:03 +09:00
20281737b1 Set explicit Content-Length: 0 when initiating MPU (#1696)
This works around a GCS quirk that incorrectly requires this header.
Fixes #1661.
2021-06-25 18:36:40 +09:00
0555c4216e Added test case for utimens is calling during multipart upload 2021-06-21 17:20:24 +09:00
5b6684ca19 Fixed a bug utimens is calling before flush 2021-06-21 17:20:24 +09:00
c4ac923b4c Ensure NUL-terminated result after strncpy (#1694)
Long symlinks may cause that the result buffer is filled and not proper
terminated with a null byte.
2021-06-21 08:08:56 +09:00
cc022a68f4 Fixed a bug in s3fs_write 2021-06-20 23:13:44 +09:00
1571379304 Set LC_ALL=en_US.UTF-8 in tests (#1691)
This allows tests to pass using the S3Proxy filesystem provider.
References #1665.
2021-06-20 19:27:25 +09:00
858562ed53 Fixed comparison warning for size_t variable 2021-06-20 16:53:25 +09:00
b8724425d3 Require explicit base parameter in cvt_strtoofft (#1683)
Also convert most callers of cvt_strtoofft to base 10 which avoid the
magical behavior of interpreting a leading 0 as octal.
References #1682.
2021-06-20 11:00:15 +09:00
b9ce0faee2 Set Content-MD5 header even for empty objects
The Content-MD5 header is required for any request to upload an object
with a retention period configured using Amazon S3 Object Lock
2021-06-19 16:10:58 +09:00
1e0e2752bf Improve warning for terminated threads
with non-zero return code.
2021-06-18 07:54:38 +09:00
7a488b93d0 Set decimal base for converting subseconds to int
The leading 0 triggers an automatic conversion as an octal value. This
fails because it is a decimal value.

Setting the base to 10 prevents this automatism and treats the value
as a decimal value.

Fixes: [WAN] string_util.cpp:cvt_strtoofft(96): something error is occurred in convert std::string(017080564) to off_t, thus return 0 as default.

Related to #1676
2021-06-17 06:27:02 +09:00
d67b83e671 Allow configuration for temporary files directory 2021-06-16 21:29:58 +09:00
a100be9dce Prefer std::string::empty over length == 0 (#1679)
This is more concise.
2021-06-13 20:03:10 +09:00
4d39ea887e Protect orgmeta with fdent_lock (#1678)
Fixes a crash seen with the CentOS 7 builder and when running with
AddressSanitizer.  Regression introduced by
ac578d188e.  Fixes #1677.
2021-06-13 16:14:24 +09:00
7638b5b3e3 Prefer std::string::rbegin over operator[] (#1673)
This is more concise and safer due to not repeating the variable name.
We cannot use std::string::back since it is not available in C++03.
2021-06-13 13:26:38 +09:00
600cee118d Fix implicit narrowing conversions (#1672)
These do not appear to be problematic but rather just clean up warnings.
Found via clang -Wshorten-64-to-32.
2021-06-13 12:50:07 +09:00
c2c56d0263 Added info object about multipart uploading for each pseudo fd
(and fixed typo about method name)
2021-06-04 22:42:58 +09:00
ac578d188e Introduced pseudo fd and separated fd for each file opening 2021-06-04 22:42:58 +09:00
53dfd48f59 Correct usage of istringstream (#1670)
Previously this looped one more time than necessary due to the eof
check:

https://isocpp.org/wiki/faq/input-output#istream-and-eof

Remove now redundant empty check.
2021-06-02 07:14:32 +09:00
f5701fa9ad Correct typo in undefinedsanitizer config (#1669) 2021-05-29 22:07:33 +09:00
84174c560d Fix data races caused by incorrect locking (#1668)
Found via Threadsanitizer.  Fixes #1471.
2021-05-29 00:11:55 +09:00
9bf525ee7a Ensuring multipart size even when storage is low
When the temporary storage was full, the old implementation started an
upload even if there was not enough data to completely fill the minimum
multipart size or fill the user-selected multipart size.

The new implementation ensures the minimum multipart size by forcing
the user-selected multipart size.

Fixes #1591
2021-05-27 22:55:52 +09:00
4b69d4b1bb Fixed a bug when the disk capacity was insufficient in RowFlush 2021-05-22 23:11:46 +09:00
bbcccd6e98 Make storage class a string (#1663)
This allows non-standard storage classes like Google Cloud Storage
Nearline.  Fixes #1613.
2021-05-21 23:34:31 +09:00
c0bcb41175 Increase test robustness by adding LC_ALL=C (#1660)
Use C locale, because some tests check for English expressions

Fixes #1658
2021-05-20 21:19:50 +09:00
b5fef788da Additional bug fixing for not creating zero-byte object 2021-05-09 17:33:53 +09:00
42f5965d8a Fix off_t to int narrowing in PageList::GetSparseFilePages (#1654)
Found via clang-tidy.
2021-05-09 14:35:00 +09:00
d904d91252 Prefer std::map::insert over find and operator[] (#1653)
This avoids a duplicate lookups.
2021-05-09 14:11:35 +09:00
4d81a4bf68 Use same time when creating directory objects (#1652)
This avoids mismatched times and is slightly faster.
2021-05-09 13:44:59 +09:00
9abe3fa662 Use same time when creating directory objects (#1652)
This avoids mismatched times and is slightly faster.
2021-05-09 13:44:12 +09:00
9d8f1b00f7 Fixed make_random_string test code being slow on macos 2021-05-08 13:55:39 +09:00
bb6d2b1b74 Replace snprintf with string and ostringstream (#1649)
These uses are probably safe from a buffer overflow perspective but
can cause data race issues in logging due to static buffers.
2021-05-08 02:48:47 +09:00
096a230b70 Allow arbitrary size AWS secret keys (#1648)
Previously s3fs limited these to 123 characters.  Fixes #1626.
2021-05-06 22:24:38 +09:00
8ef01d37a9 Fix a few nits (#1645)
Make some strings more const, initialize members, and abort if lock
initialization fails.  Partially found via clang-tidy.
2021-05-06 19:40:35 +09:00
cb9148f6cd Update for clang-tidy 12 (#1644) 2021-05-03 09:43:18 +09:00
c4fa53ec8b Add section about storage consumption to manpage (#1639)
References s3fs-fuse#1591. References s3fs-fuse#1595.
2021-05-01 15:09:29 +09:00
1e2df406ee Add Ubuntu 21.04 to CI (#1642) 2021-04-30 23:51:55 +09:00
1dabfbe1da Update CI to latest Fedora version (#1641) 2021-04-30 20:29:28 +09:00
771bbfeac5 Do not create zero-byte object when creating file (#1640)
Previously s3fs created this object to store metadata and overwrote it
when flushing.  This prevented use with object stores which do not
allow overwrites like HDS.  Instead only create an in-memory
representation which reduces the time to create small files.
Fixes #1013.
2021-04-30 19:56:33 +09:00
3694786112 Propagate errno instead of EIO (#1638)
This improves error fidelity.  Follows on to
b70f8db037.  References #1523.
2021-04-30 07:09:00 +09:00
e477d7d186 Add note about Homebrew and FUSE (#1637) 2021-04-25 21:35:08 +09:00
fbf3c83019 Consider S3 errors in HTTP PUT 200 responses (#1635)
S3 can emit these in unusual situations.  Fixes #1317.
2021-04-25 13:18:11 +09:00
8a51a26819 Allow truncation of open and modified files
Regression introduced in f5bf41cf11.
Fixes #1575.
2021-04-25 12:35:35 +09:00
1838f52e19 Declare undefined symbols for fallocate function 2021-04-25 10:12:25 +09:00
e9eb248f2f Fail CheckBucket when S3 returns PermanentRedirect (#1630)
Previously s3fs allowed mounting but all operations returned EIO.
References #693.

Co-authored-by: Takeshi Nakatani <ggtakec@gmail.com>
2021-04-24 18:46:24 +09:00
77581eda59 Change in ibm iam endpoint 2021-04-21 21:42:55 +09:00
7f3e423bbe Preserve sub-second time precision (#1624)
Found via pjdfstests.  References #897.  References #1589.
2021-04-18 13:11:12 +09:00
706e3cbebd Update ctime and mtime when opening with O_TRUNC (#1623)
Found via pjdfstests.  References #1589.
2021-04-15 07:08:49 +09:00
2effffd8e2 Fixed codes for cppcheck 2.4.1 2021-04-13 21:12:35 +09:00
2908878988 Fixed codes for cppcheck 2.4.1 2021-04-13 21:12:35 +09:00
01a26a9011 Do not allow open with O_RDONLY and O_TRUNC (#1620)
Found via pjdfstests.  References #1589.
2021-04-13 07:28:10 +09:00
23e1fbf7b9 Update ctime when truncating file (#1619)
Found via pjdfstests.  References #1589.
2021-04-13 07:08:06 +09:00
ed2e877bb6 Return EACESS when lacking required executable bit (#1617)
This makes the check consistent with read and write.  Found via
pjdfstests.  References #1551.  References #1589.
2021-04-11 22:39:27 +09:00
3663082a01 Do not allow renaming to a non-empty directory (#1604)
Found via pjdfstests.  References #1589.
2021-03-28 19:10:52 +09:00
9645d57c05 Translate KeyTooLongError to ENAMETOOLONG (#1602)
AWS does not support keys longer than 1024 characters.  Add special
handling for HeadObject which does not have a response body.
Found via pjdfstests.  References #1589.
2021-03-28 13:17:41 +09:00
f6fbd75320 Return EFBIG when file exceeds multipart limit (#1600)
Found via pjdfstests.  References #1589.
2021-03-28 12:33:01 +09:00
20a6c9d35d Update to S3Proxy 1.8.0 (#1598)
Notably this fixes an issue with the filesystem backend which returned
the incorrect Content-Type for some directories.  It also reduces
memory use with GetObject using range requests with large objects.
References #1543.

Release notes:

https://github.com/gaul/s3proxy/releases/tag/s3proxy-1.8.0
2021-03-28 11:56:10 +09:00
0a90a40569 remove duplicate line from README.md 2021-03-27 19:03:15 +09:00
ef079f4e94 Don't ignore nomultipart when storage is low
When the temporary storage filled up, the old implementation uploaded
all data with multipart uploads, even if "nomultipart" was set.

The new implementation emits a warning and returns -ENOSPC instead.

Fixes #1595
2021-03-10 08:23:54 +09:00
b589ebec23 Output version and command parameters at startup 2021-03-06 19:11:57 +09:00
8c58ba8ac0 Update ChangeLog and configure.ac for 1.89 (#1584)
Also make formatting more consistent.  Fixes #1588.

Co-authored-by: Takeshi Nakatani <ggtakec@gmail.com>
2021-02-24 08:03:55 +09:00
a19d223434 Bypass an OSX test(no different from other OS) which takes very time consuming 2021-02-23 20:47:51 +09:00
fc06419549 Fixed aws command error by rsa on ubuntu16.04 (#1585) 2021-02-23 11:41:52 +09:00
032fcf2a47 Allow optional issuing of ListObjectsV2 (#1583)
This allows use of s3fs on object stores that do not implement
the V1 API.  Fixes #1573.
2021-02-23 09:45:13 +09:00
5b5bc3114a Fixed a bug that padded null bytes when changing xattr 2021-02-21 12:23:36 +09:00
81e267d421 Fixed the same bug in chmod/chown/utimens and added tests 2021-02-20 23:30:50 +09:00
4fc92d59f3 Fixed a bug that filling NULL bytes when changing the attribute after renaming 2021-02-20 23:30:50 +09:00
a0f347b10f Added no_time_stamp_ms option mainly for testing 2021-02-20 20:24:26 +09:00
5debf523b0 Allow changing temporary directory used for tests
Set temporary directory to $TMPDIR if set or use default /var/tmp
2021-02-19 13:59:23 +09:00
1c8aadafd1 Fix typo in an error message of the test suite 2021-02-19 13:59:23 +09:00
d33f252404 Fixed forgetting to clean up test files 2021-02-14 00:07:46 +09:00
4da56acdcc Improved processing when HEAD response is 400 2021-02-13 17:00:13 +09:00
493802a605 Fixed osx mistype declaration and typo warnings 2021-02-13 12:04:35 +09:00
22b0ae9d51 set IsExpireTime to true by default
fixes #1563
2021-02-12 12:20:47 +09:00
134a54b32f Allow configuring the multipart threshold (#1562)
Also change default which improves write performance for files >= 25
MB and <= 5 GB, particularly over lossy networks.

Co-authored-by: Takeshi Nakatani <ggtakec@gmail.com>
2021-02-11 23:35:46 +09:00
7f6fbb0021 Correct singlepart_copy_limit unit (#1561)
This is documented to be in MB not KB.

Co-authored-by: Takeshi Nakatani <ggtakec@gmail.com>
2021-02-11 22:53:50 +09:00
ec8bae9827 Do not periodically flush with nomultipartupload (#1559)
s3fs periodically flushes data to S3 and hole-punches the written
data, marking it as clean.  Without multipart copy, s3fs would write
the now-zeroed data along with any new data.  s3fs should not attempt
to periodically flush dirty data at all without multipart copy
support.  Fixes #1542.
2021-02-11 22:24:39 +09:00
a4d916af13 Allow configuring multipart copy size (#1555)
Also align configuration with mixupload.
2021-02-08 20:32:12 +09:00
32f096fa3f Use clock_gettime instead of gettimeofday 2021-02-08 10:19:28 +09:00
c692093921 Copy at most 5 GB per multipart copy part request (#1553)
Previously mixupload failed with larger objects due to the AWS
constraint on part sizes.  This symptom was seen more frequently due
to periodic flushing of dirty data.  Fixes #1547.
2021-02-07 23:10:07 +09:00
1a6d0826b5 Allow -1 value to disable max_dirty_data (#1552)
This matches the man page.
2021-02-07 22:14:31 +09:00
f2c5e38724 Allow integration tests to use larger files (#1548)
Previously these failed due to dd only copying 32 MB from /dev/urandom
and exhausting the limited space in /tmp.  References #1543.

Co-authored-by: Takeshi Nakatani <ggtakec@gmail.com>
2021-02-07 12:50:02 +09:00
bf33fe7f55 Increase buffer size to avoid warning (#1550)
This can be up to 54 bytes.

Co-authored-by: Takeshi Nakatani <ggtakec@gmail.com>
2021-02-07 12:26:58 +09:00
ff9d6a75c7 Parse more specific AWS error codes (#1549)
Fixes #1545.
2021-02-07 11:29:08 +09:00
4c6690f5f0 Add timestamps to debug log and cache integrity check (#1540)
* Add UTC timestamp to debug output

for easier correlation with external events

Old output:
$ s3fs mybucket /bucket/  -o curldbg,dbglevel=debug -d -d -f
[CRT] s3fs_logger.cpp:LowSetLogLevel(201): change debug level from...
[INF]     s3fs.cpp:set_mountpoint_attribute(3989): PROC(uid=0, ...

New output:
$ s3fs mybucket /bucket/  -o curldbg,dbglevel=debug -d -d -f
2021-01-28T21:09:16.264Z [CRT] s3fs_logger.cpp:LowSetLogLevel(202):...
2021-01-28T21:09:16.264Z [INF]     s3fs.cpp:set_mountpoint_attrib...

* Add UTC timestamp to cache integrity check

for easier correlation with external events.

$ s3fs mybucket /mybucket  -oset_check_cache_sigusr1=/tmp/check.cache

Old output:
$ kill -s SIGUSR1 $(pgrep s3fs)
$ cat /tmp/check.cache
------------------------------------------------------------
Check cache file and its stats file consistency
------------------------------------------------------------
------------------------------------------------------------
Summary - Total files:                0
          Detected error files:       0
          Detected error directories: 0
------------------------------------------------------------

New output:
$ kill -s SIGUSR1 $(pgrep s3fs)
$ cat /tmp/check.cache
---------------------------------------------------------------------------
Check cache file and its stats file consistency at 2021-01-30T13:04:14.111Z
---------------------------------------------------------------------------
---------------------------------------------------------------------------
Summary - Total files:                0
          Detected error files:       0
          Detected error directories: 0
---------------------------------------------------------------------------

* Fix indentation of S3fsLog::GetCurrentTime()
2021-02-04 10:41:29 +09:00
67b9381825 Remove limit for single-part objects
AWS enforces a 5 GB limit for single-part objects but other S3
implementations like GCS support larger objects.  Fixes #1542.
2021-02-04 09:19:37 +09:00
4b53d4bf6b Suppress spurious SHA256 error message (#1544) 2021-02-04 07:28:51 +09:00
ed85b72bf5 Add warning for failing metadata updates of large files
Metadata updates fail for large files if "-o nocopyapi" or
"-o nomultipart" is set.

This change is related to #1528
2021-01-28 10:20:32 +09:00
17fda89ae9 Handle s3fs_get_content_md5 and s3fs_sha256_hex_fd errors (#1534)
Follows on to 4d833a4fb9.
2021-01-25 19:08:14 +09:00
1987bcbea3 Re-fix retry logic (#1533)
This logic has always been broken but happened to try one time due to
&& operator precedence.  7158e50ee2
broke this further when quoting && since the command was not
evaluated.
2021-01-25 18:32:40 +09:00
d019dda4f7 Simplify substr manipulations with erase (#1532)
This avoids creating a new std::string.
2021-01-25 18:02:32 +09:00
dc9255bc5f Prefer static_cast where possible (#1531) 2021-01-25 08:15:17 +09:00
b0e8758b63 Use result instead of res for consistency (#1530) 2021-01-25 07:56:10 +09:00
6d65e30dd5 Fixed brew install with cask in github actions workflow 2021-01-21 17:34:03 +09:00
b70f8db037 Propagate errno from get_local_fent (#1525)
Follows on to 4d833a4fb9.
References #1523.
2021-01-20 23:21:14 +09:00
4d833a4fb9 Return more specific errno when available (#1520)
Previously s3fs threw away some function return values and returned
EIO instead.  This was due to not trusting the mix of -1 and errno
return codes.  Correct the obviously incorrect ones via visual
inspection.  Stronger typing may find more occurrences.  Fixes #1519.
2021-01-18 18:50:49 +09:00
a6563211af Update ChangeLog and configure.ac for 1.88 2021-01-11 17:59:28 +09:00
8d66b0e4a8 Updated ChangeLog for release 1.88 (#1514)
References #1511.
2021-01-05 16:46:41 +09:00
555c1dde3d Use Gtihub Actions instead of Travis CI 2021-01-04 23:46:54 +09:00
b04bca37a5 Add configuration for Chaos HTTP Proxy (#1508)
This can find errors in retry logic.  Chaos HTTP Proxy does not
support SSL bouncestorage/chaos-http-proxy#1 so users must set
s3proxy.endpoint and run via:

CHAOS_HTTP_PROXY=1 S3_URL=http://127.0.0.1:8080 make check -C test

It can also be helpful to increase retries and reduce sleep times.
References #1504.
2021-01-04 23:32:04 +09:00
168e588ac7 fix: Add reset offset (#1503) 2021-01-04 22:57:56 +09:00
7158e50ee2 Quote | and && to allow passing it to retry (#1506) 2021-01-04 22:28:40 +09:00
bd0fadbe5f Remove authorization header when remaking handle (#1505)
This avoids including Authorization in SignedHeaders.  s3fs will
recreate the Authorization header before sending the request.
2021-01-04 21:37:34 +09:00
d1c638ab7a fix 404 error message 2020-12-30 14:10:17 +09:00
51f65d7b14 fix: miss header when retry 2020-12-23 22:16:07 +09:00
a16d00d673 Simply curl_slist_sort_insert (#1494)
Some good taste from Linus:
https://github.com/mkirchner/linked-list-good-taste
Also avoid an allocation when replacing a value and tighten up tests.
2020-12-23 20:29:33 +09:00
4d0daddad4 Fixed about Github Actions failure(centos8 and macos) (#1498) 2020-12-23 19:34:04 +09:00
d246b9e8bf Update README for change in brew arguments
* Homebrew changed the arguments required to install casks. Previously,
  `brew cask install <package>` was the correct syntax, but now it's
  `brew install --cask <package>`. This small commit updates the
  instructions for installing `osxfuse` to reflect this change
2020-12-22 11:14:24 +09:00
ef3d4e506d Update README note on eventual consistency
AWS promise read-after-write consistency now, but presumably non-AWS S3-compatible services are still eventually consistent.
2020-12-15 08:50:53 +09:00
462b37b0bb Added Github Actions workflow 2020-12-05 22:57:40 +09:00
4341291cc2 Changed a condition of the atime test(fixed #1477) (#1487) 2020-12-03 02:45:05 +09:00
c589886ba5 Added a condition to the atime test (#1477) 2020-12-02 23:21:25 +09:00
d0363b118e Add tests for curl_util (#1481) 2020-11-24 21:37:09 +09:00
533322859d Added comment for nullPointerRedundantCheck/cppcheck2.2 2020-11-21 20:06:14 +09:00
f8d5b76edb Simplify handling of returned ETag (#1479)
This works around lifetime warnings uncovered by cppcheck.
References #1478.
2020-11-21 06:56:05 +09:00
834862f8a4 Add S3_ENDPOINT test variable (#1476) 2020-11-15 22:10:26 +09:00
d9f6469b7b Fixed flushing dirty data and compressed the cache size 2020-11-14 16:45:37 +09:00
852e6ee4c6 Fixed .gitignore for src/test_string_util.cpp 2020-11-14 16:22:30 +09:00
ecb24c9c26 Disable preprocessor warnings w/o optimizations (#1473)
This removes some fortify source warnings.  Also disable failing
memory sanitizer.
2020-11-09 21:48:07 +09:00
543231c9f2 Address warnings from clang-tidy 11 (#1470) 2020-11-09 21:15:20 +09:00
d96a08d4ad fixup! Implement AWS IMDSv2 support 2020-11-07 14:48:52 +09:00
f2f930300a Implement AWS IMDSv2 support
AWS IMDSv2 is a session oriented method for retrieving instance metadata,
including IAM credentials, in Amazon EC2.  It is enabled by default in
non-enforcing mode in AWS (meaning it retains backwards compatibility with
existing IMDSv1 clients), but can be switched to enforcing mode, in which
clients are required to return API tokens with requests.

With this change, we implement support for IMDSv2 and enable it by default when
IAM roles are our source for authentication credentials.  In the event that
s3fs is running in cloud environment offering an IMDSv1-compatible API, we
support graceful fallback to that mode.  It can also be selected explicitly via
the imdsv1only mount option.

More details on IMDSv2 are available at
https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html
and
https://aws.amazon.com/blogs/security/defense-in-depth-open-firewalls-reverse-proxies-ssrf-vulnerabilities-ec2-instance-metadata-service/

Signed-off-by: Noah Meyerhans <nmeyerha@amazon.com>
2020-11-07 14:48:52 +09:00
81ad3ce0ae Fix directory authority 2020-11-07 14:47:53 +09:00
38e1eaa8a3 Added logfile option for non-syslog logging 2020-10-19 20:10:19 +09:00
6aa786b886 Flush dirty data after a writing a number of bytes (#1448)
This allows s3fs to write large files without consuming a large amount
of temporary local storage but can slow uploads due to server-side
copies.  References #617.  Fixed #1056.  Fixes #1257.
2020-10-13 22:30:42 +09:00
58750cc441 Fixed a bug that symlink could not be read after restarting s3fs 2020-10-11 22:14:36 +09:00
2188fb067e Merge pull request #1446 from gaul/use-cache/relative-path
Allow relative path with use_path
2020-10-10 23:13:07 +09:00
910255745e Allow relative path with use_path
Fixes #1161.
2020-10-10 18:13:23 +09:00
cf86fa51b0 Merge pull request #1441 from gaul/coverity
Suppress false positive from Coverity
2020-10-04 23:44:51 +09:00
a4e4ce8aea Merge pull request #1440 from gaul/test/undefined-behavior-sanitizer
Add memory and undefined behavior sanitizer
2020-10-04 23:19:36 +09:00
7f43b7fa53 Add memory and undefined behavior sanitizer
Remove Valgrind which duplicates the sanitizers and is much slower.
2020-10-04 22:55:27 +09:00
0492f75197 Merge pull request #1439 from gaul/run-once
Protect curl_warnings_once with a mutex
2020-10-04 22:43:56 +09:00
493cf20f95 Merge pull request #1435 from gaul/no-exceptions
Remove exceptions from s3fs_strtoofft
2020-10-04 22:19:25 +09:00
3553fb65a0 Suppress false positive from Coverity 2020-10-04 14:58:13 +09:00
059cc57ba6 Added atime and Corrected atime/mtime/ctime operations 2020-10-04 13:54:01 +09:00
4df4ffe06f Protect curl_warnings_once with a mutex
This allows ThreadSanitizer to run without warnings.
2020-10-03 21:09:35 +09:00
462347256d Changed the message level in the AutoFdEntity::GetFdEntity 2020-10-03 20:41:17 +09:00
133feb67c3 Merge pull request #1434 from gaul/const-string
Use const std::string& where possible
2020-10-03 10:02:03 +09:00
be308e9d11 Merge pull request #1436 from ggtakec/fix_code
Fixed signature error due to case of hex string
2020-10-03 03:44:49 +09:00
2cf195741c Fixed signature error due to case of hex string 2020-10-02 18:09:13 +00:00
f61baada46 Merge pull request #1433 from gaul/hex
Further simplify and centralize hex conversion
2020-10-03 00:34:02 +09:00
6e1e0d1d31 Merge pull request #1432 from gaul/v2-or-v4
Add sigv4 flag and fix v4 regression
2020-10-03 00:09:55 +09:00
66419e7292 Merge pull request #1431 from gaul/string/find_first_of
Prefer string::find_first_of(char) where possible
2020-10-02 23:42:17 +09:00
9e998877e9 Merge pull request #1430 from gaul/ostringstream
Simplify use of ostringstream
2020-10-02 23:26:41 +09:00
5ebd4039e6 Merge pull request #1426 from gaul/is_prefix
Call is_prefix instead of compare and substr
2020-10-02 23:03:10 +09:00
3628b9d1e2 Remove exceptions from s3fs_strtoofft
Explicit return codes are simpler and safer.
2020-10-02 22:53:12 +09:00
8d2bd874d7 Use const std::string& where possible
This hints to callers on usage.
2020-10-02 08:48:43 +09:00
7e27c6cf7d Further simplify and centralize hex conversion 2020-10-01 23:31:06 +09:00
b8ff4ede49 Sign GET requests with V4 signature correctly
This bug was previously masked by v2 fallback.  Fixes regression from
81805715bd.
2020-10-01 20:03:14 +09:00
081d6c1245 Allow setting signature V4-only
Default to allowing V2 or V4.
2020-10-01 20:03:14 +09:00
eb8004c355 Prefer string::find_first_of(char) where possible 2020-10-01 18:24:45 +09:00
b3bf9f8f54 Simplify use of ostringstream
Resetting this does not re-use the underlying buffer so creating a new
ostringstream has similar efficiency.
2020-10-01 17:55:34 +09:00
503c86bb8a Call is_prefix instead of compare and substr 2020-09-27 22:19:54 +09:00
757f4caee8 Merge pull request #1425 from gaul/create-bucket/sse
Do not send SSE headers during bucket creation
2020-09-27 11:34:15 +09:00
95fabd1f3a Merge pull request #1423 from gaul/nettle
Fix MD5 when using gnutls with nettle
2020-09-27 11:17:55 +09:00
0b42e08636 Merge pull request #1422 from gaul/c++/append-assign-at
Remove calls to append, assign, and at
2020-09-27 10:59:48 +09:00
d5e4f99e72 Merge pull request #1413 from liuyongqing/master
not call put headers if not exist pending meta
2020-09-27 10:37:22 +09:00
781d4dd857 Merge pull request #1424 from gaul/travis/ppc64
Disable builder for linux-ppc64le
2020-09-27 10:18:52 +09:00
f35fe850c0 Do not send SSE headers during bucket creation
This allows integration tests to pass with use_sse.
2020-09-26 13:25:18 +09:00
7102b9eb74 Disable builder for linux-ppc64le
This works around a travis-ci.com Java/S3Proxy incompatibility.  Also
fix vim formatting.  References #1415.
2020-09-25 23:25:36 +09:00
9a55c9fd9f Fix MD5 when using gnutls with nettle
This matches the non-nettle definition of s3fs_md5_fd.
2020-09-25 23:07:50 +09:00
041b4ec05c enforce exact key match in IBM IAM response 2020-09-25 22:41:19 +09:00
2438066d52 Remove calls to append, assign, and at
operator+, operator=, and operator[] are more idiomatic and consistent
with the code base.
2020-09-25 12:19:51 +09:00
3c5b35b3b9 Update README.md for migrating travis-ci.com 2020-09-21 18:59:45 +09:00
e98827ec6f not call put headers if not exist pending meta 2020-09-21 14:12:07 +08:00
864941d4d5 Merge pull request #1414 from gaul/clang-tidy/misc
Fix clang-tidy warnings
2020-09-21 07:49:59 +09:00
05863a3178 Fix clang-tidy warnings 2020-09-21 07:03:42 +09:00
075d161bb1 Merge pull request #1408 from gaul/env
Ensure environment variable is set when using ECS
2020-09-20 13:01:17 +09:00
f8b5c911ed Merge pull request #1407 from gaul/pid
Rework s3fs pid handling
2020-09-20 12:32:32 +09:00
6f40503328 Merge pull request #1406 from gaul/strcmp
Remove unnecessary calls to strcmp(str.c_str())
2020-09-20 11:28:41 +09:00
3440c3348c Merge pull request #1405 from gaul/is-prefix
Rename STR2NCMP to is_prefix for clarity
2020-09-20 10:03:53 +09:00
853be26612 Merge pull request #1404 from liuyongqing/master
fix dead lock in disk insufficient and optimize code
2020-09-20 01:34:02 +09:00
89b1c32b24 Rework s3fs pid handling
Previously S3FS_PID was not set in the correct shell and thus
ps u $S3FS_PID showed all programs.  This caused the flag detection to
fail when users ran other instances of s3fs with different flags.
References #1402.
2020-09-18 22:05:37 +09:00
44d2cc15f7 Ensure environment variable is set when using ECS
Previously s3fs crashed when AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
was not set.  References #1162.
2020-09-18 08:14:58 +09:00
76d88f2291 Merge pull request #1403 from gaul/vim/expandtab
Fix expandtab settings for tests
2020-09-17 21:35:58 +09:00
72340cfbd9 Merge pull request #1401 from gaul/test/hardlink
Add test for hardlink
2020-09-17 20:04:07 +09:00
81805715bd Remove unnecessary calls to strcmp(str.c_str()) 2020-09-17 20:00:45 +09:00
ebcbb02d16 Rename STR2NCMP to is_prefix for clarity
This may prevent confusion seen in
39ec8e242e.
2020-09-17 19:45:54 +09:00
8c29b60129 Merge pull request #1400 from gaul/test/concurrent-read
Add test for concurrent reads
2020-09-17 19:26:44 +09:00
93cf67c65d Merge pull request #1399 from gaul/md5-sha256
Use more descriptive names for digest functions
2020-09-17 17:11:19 +09:00
211cc0f5f2 fix dead lock in disk insufficient and optimize code 2020-09-16 22:45:28 +08:00
8fb70c5e4a Fix expandtab settings for tests
This matches the main source.
2020-09-15 22:11:14 +09:00
c58c91fc4f Merge pull request #1398 from gaul/memset
Remove unneeded memset calls
2020-09-15 22:09:54 +09:00
78e2345c19 Add test for hardlink 2020-09-15 22:07:25 +09:00
3bc565b986 Add test for concurrent reads 2020-09-15 21:25:51 +09:00
b7187352e1 Use more descriptive names for digest functions
Previously they used hex to refer to binary data which is confusing
since other std::string return types are actually hex.  Also remove
unused s3fs_md5sum.
2020-09-15 21:18:58 +09:00
1520ca6220 Merge pull request #1397 from gaul/hex
Centralize hex conversion
2020-09-15 21:14:23 +09:00
f7a63d5c97 Merge pull request #1396 from gaul/32-bit-read
Use off_t for read sizes
2020-09-15 20:05:19 +09:00
3958450c05 Added a class for automating fdentity reference counts 2020-09-14 22:02:28 +09:00
5121c73ed1 Remove unneeded memset calls
Also use constant for array lengths.
2020-09-14 19:51:36 +09:00
44eaac8471 Centralize hex conversion 2020-09-14 19:28:59 +09:00
77501c3600 Use off_t for read sizes
This fixes an issue with large multipart_size on 32-bit platforms like
Raspberry Pi.
2020-09-14 18:12:23 +09:00
8205607716 Fixed incorrect Signal related message at s3fs initialization and termination 2020-09-13 18:54:10 +09:00
c7132b7f56 Merge pull request #1390 from gaul/namespace-std
Remove uses of implicit namespace std
2020-09-13 13:26:22 +09:00
1043e08dfa Remove uses of implicit namespace std
Fixed via:

sed -i '/using namespace std/{N;d}' src/*.cpp
sed -i 's/ string/ std::string/g' src/*.cpp
sed -i 's/(string/(std::string/g' src/*.cpp
sed -i 's/\[string/\[std::string/g' src/*.cpp
sed -i 's/^string/std::string/g' src/*.cpp
sed -i 's/ ifstream/ std::ifstream/g' src/*.cpp
sed -i 's/ istringstream/ std::istringstream/g' src/*.cpp
sed -i 's/ ostringstream/ std::ostringstream/g' src/*.cpp
sed -i 's/ max(/ std::max(/g' src/*.cpp
sed -i 's/ min(/ std::min(/g' src/*.cpp
sed -i 's/ endl/ std::endl/g' src/*.cpp
2020-09-13 11:57:20 +09:00
e5f4f9b69e Merge pull request #1393 from gaul/32-bit-casting
Fix casting warnings on 32-bit platforms
2020-09-13 10:40:56 +09:00
1e3c10d803 Merge pull request #1392 from gaul/large-singlepart-32-bit
Use 64-bit off_t when computing digests
2020-09-13 10:39:34 +09:00
6fa4477673 Merge pull request #1389 from gaul/flags
Remove incorrect string prefix comparisons
2020-09-13 10:17:33 +09:00
6d1e704e34 Fix casting warnings on 32-bit platforms 2020-09-12 18:22:32 +09:00
ffc33a447f Use 64-bit off_t when computing digests
This allows 32-bit platforms like Raspberry Pi to upload single-part
objects larger than 2 GB.
2020-09-12 15:00:23 +09:00
39ec8e242e Remove incorrect string prefix comparisons
Previously flags like -o nouafoobar were parsed as -o noua.  Found
via:

grep STR2NCMP src/s3fs.cpp | grep -v '="'
2020-09-11 17:38:20 +09:00
0d4e39ad1c return 0 after parsing "use_session_token" arg (#1388)
return 0 after parsing "use_session_token" arg

I hope this might fix #651.

There's clearly an open bug in #651 confirmed by several users related to the parsing of the `-o use_session_token`. Looking at the source, I noticed that there was a return value everywhere except here, so I suspect this may be responsible.
2020-09-11 08:09:36 +09:00
6112eb6a49 Merge pull request #1385 from liuyongqing/master
close FdEntity to avoid leakage
2020-09-10 19:44:48 +09:00
986fab8738 close FdEntity to avoid leakage 2020-09-07 20:48:16 +08:00
b5ffd419d8 Source file division and set 4 spaces and cleanup 2020-08-26 17:43:50 +09:00
c6e23212bb Merge pull request #1375 from gaul/cppcheck
Add const where possible
2020-08-21 07:32:39 +09:00
e75c11956c Merge pull request #1374 from gaul/deep-archive
Add support for deep archive storage class
2020-08-21 07:01:43 +09:00
1ec8528502 Add const where possible
Found via cppcheck 2.1
2020-08-20 23:46:11 +09:00
892e7129c5 Add support for deep archive storage class 2020-08-20 23:42:45 +09:00
bdea2ee5c8 Merge pull request #1373 from gaul/enum
Use scoped enums for acl_t, sse_type_t, and storage_class_t
2020-08-20 23:06:52 +09:00
a5186c73c2 Merge pull request #1365 from ggtakec/check_lseek
Dynamically determine whether lseek extended options are supported
2020-08-20 22:36:56 +09:00
4580e6ff93 Merge pull request #1364 from ggtakec/test_nospace_mv
Added mv file test when disk space is insufficient
2020-08-20 22:08:09 +09:00
60d456a993 Use scoped enums for acl_t, sse_type_t, and storage_class_t
This prevents some kinds of implicit conversions.  Also deduplicate
str/from_str logic.  References #1371.
2020-08-20 18:46:18 +09:00
bcf6838e86 Merge pull request #1370 from gaul/vim/modeline
Correct vim modeline to 2-space indentation
2020-08-19 22:44:40 +09:00
41a66d9706 Merge pull request #1368 from gaul/curl-lock
Prefer named locks in curl
2020-08-19 22:17:32 +09:00
958ad83a4b Correct vim modeline to 2-space indentation 2020-08-19 21:03:46 +09:00
ba61470bae Prefer named locks in curl
This removes the confusing and unsafe pthread_mutex_t array.
2020-08-18 22:20:41 +09:00
0e895f60a0 Merge pull request #1366 from gaul/curl_handles_lock
Consistently lock curl_times and curl_progress
2020-08-17 19:27:21 +09:00
8210a1b2f2 Consistently lock curl_times and curl_progress
References #1362.
2020-08-17 09:47:38 +09:00
2feefeec47 Added mv file test when disk space is insufficient 2020-08-16 12:47:29 +00:00
55cb8920d5 Dynamically determine whether lseek extended options are supported 2020-08-16 12:37:11 +00:00
46acbf10ba Merge pull request #1363 from gaul/is-modified-race
Lock fdent_data_lock before accessing pagelist
2020-08-16 20:25:24 +09:00
f28e3bd89e Merge pull request #1362 from gaul/test/sanitizers
Add script to run tests using sanitizers
2020-08-16 19:15:05 +09:00
2c0408b95a Merge pull request #1357 from gaul/readdir
Call readdir instead of readdir_r
2020-08-16 18:50:38 +09:00
057da86d87 Merge pull request #1356 from gaul/printf-size_t
Prefer %zd and %zu for ssize_t and size_t
2020-08-16 18:16:59 +09:00
8de6cb3504 Lock fdent_data_lock before accessing pagelist
Found via ThreadSanitizer.  References #1353.  References #1362.
2020-08-16 17:44:03 +09:00
2bb745cdd7 Fixed a bug about move file over limit of ensure space 2020-08-16 17:42:20 +09:00
35090ba4d5 Call readdir instead of readdir_r
Only a single thread uses this directory stream.  Further, modern
implementations are thread-safe by default and deprecated this call:

https://man7.org/linux/man-pages/man3/readdir_r.3.html
2020-08-16 13:33:23 +09:00
132a1bebbb Prefer %zd and %zu for ssize_t and size_t
This removes unnecessary casting.
2020-08-15 17:30:23 +09:00
c8e13300e1 Add script to run tests using sanitizers
These currently show several kinds of errors.
2020-08-15 17:28:35 +09:00
a23d02923c add storage providers 2020-08-13 15:09:33 +09:00
194262c0ef Update ChangeLog and configure.ac for 1.87
Fixes #1335.
2020-08-10 11:52:14 +09:00
e2fbcb4d30 Merge pull request #1348 from gaul/readme/ibm
Move IBM information to Non Amazon S3 wiki page
2020-08-03 00:55:11 +09:00
0c1bc0f803 Add portability wrapper for stat(1)
Fixes #1344.
2020-08-02 23:14:58 +09:00
83361e7905 Add some code backticks to README 2020-08-02 23:02:11 +09:00
19abd9ffaf Move IBM information to Non Amazon S3 wiki page
This gives consistency with other providers:

https://github.com/s3fs-fuse/s3fs-fuse/wiki/Non-Amazon-S3
2020-08-01 20:22:30 +09:00
cbd925c56f Moved the SIGUSR2 handler to S3fsSignals class 2020-07-28 14:54:35 +09:00
63bbb47378 Merge pull request #1341 from gaul/stat-cache/default
Change default stat_cache_expire
2020-07-26 23:54:14 +09:00
0fbd0eac80 Change default stat_cache_expire
Previously s3fs cached files forever which confused users with
creating objects using another client.
2020-07-26 23:04:43 +09:00
e5231fa3c7 Merge pull request #1340 from gaul/test/external-directory
Test creating a directory with external program
2020-07-26 22:06:40 +09:00
ad1961417d Added SIGUSR1 option for cache file integrity test 2020-07-26 21:04:11 +09:00
4154e539ea Test creating a directory with external program
References #1264.
2020-07-25 21:22:53 +09:00
e0a38adaf6 Merge pull request #1333 from ggtakec/similar_processing
Put similar processing together into method GetCacheFileStatTopDir
2020-07-12 20:29:45 +09:00
c3e711da58 Merge pull request #1327 from pxeger/master
`s3fs#bucketname ... fuse` -> `bucketname ... fuse.s3fs` (#1321)
2020-07-12 19:14:27 +09:00
700e288718 Put similar processing together into method GetCacheFileStatTopDir 2020-07-12 08:12:02 +00:00
e72a64785b Merge pull request #1331 from gaul/travis/simplify
Simplify conditional statements
2020-07-12 12:52:21 +09:00
5ace2b70fc Simplify conditional statements 2020-07-10 19:34:46 +09:00
62c8be85d6 Interim fix for Travis macOS Build 2020-07-10 09:47:18 +09:00
3f6b5ae6a5 Merge pull request #1329 from gaul/cppcheck-2.1
Fix NULL pointer deference
2020-07-09 23:00:36 +09:00
dc365b65a0 Fix NULL pointer deference
Found via cppcheck 2.1.
2020-07-09 21:40:23 +09:00
9c88ec2128 Merge pull request #1326 from gaul/test/python2
Use Python 2 for write_multiple_offsets
2020-07-09 18:45:41 +09:00
3dd9832f61 s3fs#bucketname ... fuse -> bucketname ... fuse.s3fs (#1321) 2020-07-07 16:06:00 +01:00
4d1f5c899f Use Python 2 for write_multiple_offsets
This aligns with ut_test.py .  Using an older Python also allows
compatibility with the older macOS 10.12 Travis CI.  References #1323.
2020-07-07 21:12:52 +09:00
1f796d432d Fixed upload error about mixuploading sparse file and truncating file 2020-06-27 22:44:19 +09:00
35006e318f Fixed about ParallelMixMultipartUpload 2020-06-24 12:48:55 +09:00
7d0c66e08a Add support for glacier storage class.
Just a copy of what have been done in PR #271.
2020-06-23 11:23:21 +09:00
9dc4148743 Merge pull request #1312 from ggtakec/fix_bug_cache
Fixed a bug about serializing from cache file
2020-06-19 22:54:39 +09:00
f324d8e04f Fixed a bug about serializing from cache file 2020-06-19 12:57:27 +00:00
f16ee96d7e Merge pull request #1306 from gaul/http/500
Retry with exponential backoff during 500 error
2020-06-06 15:30:22 +09:00
0d849b38c2 Merge pull request #1305 from gaul/alibaba/multipart
Ignore case when comparing ETags
2020-06-06 15:05:39 +09:00
8ed020610f Merge pull request #1296 from gaul/test/oss
Import ossfs tests
2020-06-06 14:40:11 +09:00
d8766b2051 Retry with exponential backoff during 500 error
Amazon suggests retrying on both 500 and 503:

https://aws.amazon.com/premiumsupport/knowledge-center/http-5xx-errors-s3/

Fixes #1251.
2020-06-05 21:01:30 +09:00
9db70bab63 Ignore case when comparing ETags
This allows multipart upload to work with Alibaba OSS.
References #1297.
2020-06-05 18:17:52 +09:00
8a7548a9d4 Import ossfs tests
This turns up a failure in test_rename_file when calling seek(0) on a
renamed file.
2020-06-01 09:08:25 +09:00
0cb057dadd Merge pull request #1303 from gaul/rename/use_cache
Relink cache stats file atomically via rename
2020-06-01 00:10:33 +09:00
0f5db0d1bf Merge pull request #1302 from gaul/rename/nocopy
Fix renames of open files with nocopyapi option
2020-05-31 23:46:46 +09:00
94e67c9c58 Merge pull request #1301 from gaul/pthread-result
Check results from pthread mutex calls
2020-05-31 23:11:24 +09:00
274321524c Relink cache stats file atomically via rename
The new file may already exist so link may fail.  Further link/unlink
is not atomic.  Addresses an error when renaming an open with with
use_cache.  References #1296.
2020-05-31 23:09:58 +09:00
40f7007263 Check results from pthread mutex calls
Also remove some unnecessary exception handling.
2020-05-30 16:37:55 +09:00
66597ec5f2 Fix renames of open files with nocopyapi option
References #1296.
2020-05-30 15:45:43 +09:00
75e72385cc Added a parameter to output body to curldbg option 2020-05-25 08:49:01 +09:00
eb58460175 Merge pull request #1294 from gaul/test/profile
Allow overriding test credentials with a profile
2020-05-24 16:14:31 +09:00
0852521a7e Merge pull request #1293 from gaul/s3proxy
Update to S3Proxy 1.7.1
2020-05-24 15:22:00 +09:00
56ed6bb97f Merge pull request #1292 from gaul/retries
Do not allow zero retries
2020-05-24 15:03:03 +09:00
73098220bf Allow overriding test credentials with a profile 2020-05-24 12:05:16 +09:00
ca7756fa77 Update to S3Proxy 1.7.1
Release notes:

https://github.com/gaul/s3proxy/releases/tag/s3proxy-1.7.1
2020-05-23 10:06:44 +09:00
8b15db6dcb Do not allow zero retries
Retries actually means tries, e.g., if the user sets zero, s3fs will
never try an operation at all.
2020-05-23 10:05:23 +09:00
0b60aa81eb Merge pull request #1285 from ggtakec/wrapped_s3fs_strtoofft
Not abort process by exception threw from s3fs_strtoofft
2020-05-22 22:36:34 +09:00
da70cb92a8 Provide AWS CLI with correct test credentials
This allows tests to pass against real S3 implementations like
Backblaze.  References #272.
2020-05-22 19:27:18 +09:00
746a027e98 Expand on random write limitation 2020-05-05 08:12:04 +09:00
80c11b6c12 Not abort process by exception threw from s3fs_strtoofft 2020-05-03 13:46:05 +00:00
b76226a06d Merge pull request #1286 from gaul/gcs
Support Google Cloud Storage headers
2020-05-03 22:41:02 +09:00
8945e98d8b Support Google Cloud Storage headers
This allows s3fs to interpret objects created by gsutil.
2020-05-03 18:33:13 +09:00
97c249d5b9 Not abort process by exception threw from s3fs_strtoofft 2020-05-03 08:08:28 +00:00
6e134a23f9 Merge pull request #1280 from ggtakec/add_test_fdcache
Add test for cache file stat content
2020-05-03 16:33:50 +09:00
a4803543a1 Merge pull request #1282 from gaul/mime
Warn about missing MIME types instead of exiting
2020-05-03 15:15:05 +09:00
2cc88b933f Warn about missing MIME types instead of exiting
s3fs uses the MIME types file to set Content-Type for uploaded
objects.  Most distribution packages should install this via
recommended (not required) dependencies.  Users compiling from source
may not have this installed and s3fs should not prevent launching
since most users do not care about Content-Type.  Instead warn about
MIME types absence.  Fixes #1270.
2020-04-29 20:03:50 +09:00
ce1221c867 Add test for cache file stat content 2020-04-22 15:53:00 +00:00
005a684600 Fix typos 2020-04-22 21:49:11 +09:00
3af17c3019 Add test for out-of-order writes
References #1220.  References #1277.
2020-04-22 21:48:55 +09:00
f26a0aa71d Fixed insufficient upload size for mix multipart upload 2020-04-22 09:31:22 +09:00
2b4619842d Merge pull request #1278 from gaul/http-416
Add handler for HTTP 416
2020-04-21 22:38:54 +09:00
cf529e0af7 Add handler for HTTP 416
This prevents retries when the server indicates an unsatisfiable MPU
copy part request.  References #1220.
2020-04-21 19:45:10 +09:00
4da02d023b Improved strictness of cache file stats(file) 2020-04-21 19:45:03 +09:00
fe0677651e Merge pull request #1271 from ggtakec/fix_stat_file
Fixed the truncation bug of stat file for cache file
2020-04-19 16:27:11 +09:00
811ea0cb85 Fixed the truncation bug of stat file for cache file 2020-04-19 07:08:49 +00:00
a5f84535f3 Add install instructions for Arch Linux 2020-04-18 19:27:52 +09:00
84bf460f99 Remove deprecated sudo configuration
Addresses warnings of the form:

jobs.include: deprecated key sudo (The key `sudo` has no effect
anymore.)
2020-04-15 10:09:52 +09:00
538fbed302 Merge pull request #1266 from gaul/test/cache-eviction
Test cache eviction
2020-04-14 22:30:04 +09:00
feafb44bae Clean up macOS FUSE loading 2020-04-12 23:18:27 +09:00
a44fc1103d Avoid setting bogus group id
Addresses a symptom on newer macOS in Travis.
2020-04-12 22:37:22 +09:00
48a872e285 Address cppcheck 1.90 warning 2020-04-12 22:20:44 +09:00
c44a60f3f5 Fixed a bug of stats cache compression 2020-04-12 18:33:00 +09:00
f373df9682 Test cache eviction 2020-04-11 19:00:38 +09:00
9e01d5b8d1 Merge pull request #1254 from ggtakec/modify_mimetypes
Added mime option for strict checking of mime types file
2020-04-11 14:48:47 +09:00
7fbda230f5 Added mime option for strict checking of mime types file 2020-03-30 14:41:18 +00:00
56141557dc Avoid unneeded string copy
Found by clang-tidy 10.
2020-03-28 08:49:49 +09:00
fe2b269b6e Merge pull request #1253 from juliogonzalez/fix-1217
Generic compilation instructions: explain that /etc/mime.type is needed
2020-03-19 21:06:32 +09:00
eb6fe69af2 Generic compilation instructions: explain that /etc/mime.type is needed 2020-03-18 23:41:52 +01:00
6489c5d394 Merge pull request #1247 from ggtakec/fix_travis_timeout
Avoid TravisCI timeouts in test execution
2020-03-15 16:48:25 +09:00
854a8a8356 Avoid TravisCI timeouts in test execution 2020-02-24 09:56:18 +00:00
d34475d6a1 Add random writes and appends to README 2020-02-24 18:21:13 +09:00
b72f4b43a4 use correct content-type when complete multipart upload 2020-02-10 16:58:28 +09:00
34e797d6f5 Add Twitter link 2020-02-07 09:01:50 +09:00
bb20fc3c98 Update ChangeLog and configure.ac for 1.86
Fixes #1050.
2020-02-05 22:27:28 +09:00
3e66e42ae5 Merge pull request #1242 from ggtakec/bypass_test
Avoid test errors on MacOS
2020-02-05 01:29:11 +09:00
0665d78550 Temporary measure: reduce test time on MacOS 2020-02-04 15:38:19 +00:00
55d670f22f Change content-types test for MacOS 2020-02-04 14:51:50 +00:00
32ae0d2c79 Bypassed MacOS ensure_diskfree test 2020-02-04 14:00:47 +00:00
924eeb3587 Document host and servicepath
The various bits of host, url, and servicepath seem to overlap.
References #1203.
2020-02-04 21:13:29 +09:00
bc9126d774 Set directory MIME type to application/x-directory
Previously s3fs auto-detected the MIME type of directories like
"TOYOTA TRUCK 8.2.2" as application/x-troff-man.  This caused get_mode
to not set S_IFDIR which failed directory creation.  Instead force all
object names ending in / to application/x-directory.  Fixes #1183.
2020-02-04 20:03:21 +09:00
4df50e7f85 Test that s3fs automatically detects Content-Type
References #1217.
2020-02-04 19:47:09 +09:00
4e26728cbf break recursion when calling GetIAMCredentials (#1233)
break recursion when calling GetIAMCredentials
2020-01-31 16:48:37 +09:00
7135666060 Merge pull request #1234 from ggtakec/fix_dbg
Suppressed a lot of message output about cache cleanup
2020-01-31 01:00:46 +09:00
018ccb9a11 Suppressed a lot of message output about cache cleanup 2020-01-30 14:42:28 +00:00
ee1d3a9057 Merge pull request #1151 from liuyongqing/master
fix deadlock in clean up cache
2020-01-30 22:17:50 +09:00
b762a0a85b fix deadlock due to fdmanager_lock and fdent_data_lock 2020-01-29 12:03:53 +08:00
9771be29b2 Merge pull request #1232 from ggtakec/test_err_avoid
Not trap chown command errors directly
2020-01-28 20:47:54 +09:00
010a6b83ef Not trap chown command errors directly 2020-01-28 10:32:55 +00:00
87224b830b Merge pull request #1230 from ggtakec/fix_test
Fixed removing test file in integration-test-main.sh
2020-01-27 00:39:50 +09:00
9e77650e8c Fixed removing test file in integration-test-main.sh 2020-01-26 13:32:41 +00:00
e0712f444d Update source for clang-tidy 9.0.0 2020-01-13 20:56:45 +09:00
913b72fdaf Add intelligent_tiering to man page
Follows on to 39102608aa.
References #1219.
2020-01-13 20:26:01 +09:00
39102608aa Add intelligent tiering as option for storage class
Resolves Issue #1219
2020-01-13 20:24:35 +09:00
23945a0130 In memory cache for softlinks with cache out 2020-01-13 20:23:10 +09:00
bdfb9ee815 Document requester_pays option 2019-11-25 22:53:50 +09:00
1a75a94253 Merge pull request #1205 from mikelolasagasti/update-doc
Update install instructions for Debian and Fedora
2019-11-24 19:41:05 +09:00
a9d527d517 Merge pull request #1199 from ahuarte47/master_requester-pays
Adds requester_pays option to enable requests involving Requester Pays buckets
2019-11-24 17:44:34 +09:00
94666f7754 Merge pull request #1197 from bbxiao1/compilation-dependencies
Specfiy pkg-config as a necessary dependency for compilation
2019-11-24 13:28:25 +09:00
41acbaa746 Merge pull request #1200 from ggtakec/travis_cache_osx
Use travis cache for brew on osx
2019-11-24 12:47:31 +09:00
d5042a73bd Update install instructions for Debian and Fedora 2019-11-22 20:46:21 +01:00
f6756596b3 Use travis cache for brew on osx 2019-11-18 12:10:06 +00:00
a24f78f5a4 Adds requester_pays option to enable requests involving Requester Pays buckets 2019-11-18 12:38:16 +01:00
64d4b2c0b0 Specfiy pkg-config as a necessary dependency for compilation 2019-11-17 17:37:07 -07:00
cc4a307415 Add Gentoo install instructions 2019-11-05 03:44:07 +09:00
a07a5336f6 Merge pull request #1185 from bryceml/master
handle edge case when bucket name and first part of endpoint match
2019-10-31 23:42:47 +09:00
9789ca1a4d Merge pull request #1188 from gaul/s3proxy
Upgrade to S3Proxy 1.7.0
2019-10-31 23:00:35 +09:00
4ec2d685e7 Merge pull request #1181 from ggtakec/fix_1171
Fixed a rename bug
2019-10-31 22:36:34 +09:00
dc62953040 Upgrade to S3Proxy 1.7.0
Release notes:

https://github.com/gaul/s3proxy/releases/tag/s3proxy-1.7.0
2019-10-28 20:11:01 -07:00
0c42a74a8a handle edge case when bucket name and first part of endpoint match 2019-10-26 00:51:19 -06:00
cf3e82d10a Fixed a rename bug when enable_noobj_cache 2019-10-23 12:39:42 +00:00
0e815c2fbc Merge pull request #1173 from ggtakec/fixed_1171
Fixed test_write_multiple_offsets error on osx
2019-10-15 03:30:11 +09:00
27a5536749 Fixed test_write_multiple_offsets error on osx 2019-10-14 17:29:39 +00:00
db338b36b8 Merge pull request #1160 from gaul/mix_upload
Add test for writing to multiple offsets
2019-10-14 22:07:50 +09:00
72b906255f Merge pull request #1169 from ggtakec/test_brew
Updated .travis.yml for tapping homebrew/cask-cask
2019-10-14 21:38:10 +09:00
2211678d91 Updated .travis.yml for tapping homebrew/cask-cask 2019-10-14 11:44:06 +00:00
80162c126b Add test for writing to multiple offsets
References #1098.
2019-09-25 19:31:08 -07:00
1db94a0b30 Fixed to use copy api in multipart upload 2019-09-25 19:30:58 -07:00
b6349e9428 Merge pull request #1158 from ggtakec/fix_cppcheck
Fixed build error by cppcheck 1.89
2019-09-23 20:22:33 +09:00
bedd648d47 Fixed build error by cppcheck 1.89 2019-09-23 10:49:49 +00:00
58b3cce320 Merge pull request #1066 from gaul/sign-requests
Sign request immediately before sending
2019-09-23 15:58:21 +09:00
81102a5963 Merge pull request #1149 from ggtakec/fix_retry
Fixed a bug that type and op are not inherited
2019-09-08 20:32:43 +09:00
42fb30852b Merge pull request #1145 from gaul/bool
Fix a few bool types
2019-09-08 20:04:30 +09:00
e51361cb94 Merge pull request #1143 from gaul/doc/umask
Document umask flag
2019-09-08 19:49:58 +09:00
80a9ed9d6a Merge pull request #1142 from gaul/base
Expose base parameter in s3fs_strtoofft
2019-09-08 19:31:31 +09:00
e2129001eb Fixed a bug that type and op are not inherited 2019-09-08 09:59:04 +00:00
805cc064af Fix a few bool types
Found via clang-tidy.
2019-09-05 10:42:42 -07:00
3c2279db39 Document umask flag 2019-09-04 20:53:58 -07:00
412876ca33 Expose base parameter in s3fs_strtoofft
This fixes a regression from ccf3e7bfa2
which caused the misparsing of octal inputs for the mp_umask and umask
flags.  It also allows some callers to be more precise about their
decimal inputs.
2019-09-04 20:41:47 -07:00
461a346bf4 Sign request immediately before sending
Previously s3fs could create a long list of pre-signed requests which
could take longer than the default S3 clock skew limit of 15 minutes.
This also changes SHA-256 computation from single- to multi-threaded
since this is now computed in the worker threads.  Regression from
88cd8feb05.  Fixes #1019.
2019-08-29 15:35:27 -07:00
ae4bcd405c use correct content-type when overwriting and copying files 2019-08-28 22:25:09 -07:00
0536dc1112 Refixed strict processing of MultiRead method 2019-08-25 20:46:01 -07:00
1c3507ede1 Merge pull request #1135 from gaul/curl-timeout
Remove useless CURLE_OPERATION_TIMEDOUT check
2019-08-25 17:53:02 +09:00
3f47037cc7 Merge pull request #1134 from gaul/test/size
Verify file size via metadata as well as data
2019-08-25 17:34:41 +09:00
d87321ef3c Merge pull request #1133 from gaul/default-acl
Promote default ACL to enum
2019-08-25 17:05:54 +09:00
01ac815346 Remove useless CURLE_OPERATION_TIMEDOUT check
CheckBucket only returns errno and HTTP status codes.
2019-08-20 18:44:48 -07:00
2daa1d53d9 Verify file size via metadata as well as data 2019-08-20 18:36:44 -07:00
cc2eed84a5 Promote default ACL to enum
This sanity checks ACLs during initialization and also omits sending
the header when set to PRIVATE which is the default.
2019-08-20 15:05:58 -07:00
c644e4bef2 Merge pull request #1131 from ggtakec/fix_typo
Fixed typo in #1129
2019-08-14 22:26:04 +09:00
a7d83df3eb Fixed typo in #1129 2019-08-14 12:39:38 +00:00
e1886b5343 Merge pull request #1130 from ggtakec/update_multiread
Strict processing of MultiRead method
2019-08-14 00:38:59 +09:00
873e376098 Strict processing of MultiRead method 2019-08-13 15:23:13 +00:00
3c378a4a7a Merge pull request #1129 from ggtakec/update_test
Modified the test script a little
2019-08-13 23:55:17 +09:00
ca7266fb76 Modified the test script a little 2019-08-13 14:21:42 +00:00
4a0c23258e Fixed MultiRead method to exit after waiting other parts at error 2019-08-12 14:45:06 -07:00
ccc79ec139 Merge pull request #1126 from ggtakec/fix_multipart_copy_retry
Fixed multipart copy and its retry handler
2019-08-12 01:50:44 +09:00
5c4a0a862a Fixed multipart copy and its retry handler 2019-08-11 16:21:26 +00:00
2a779df4fd Merge pull request #1125 from ggtakec/fix_nocopyapi_copy
Fixed simple copy with nocpoyapi and modify flag in fdcache
2019-08-11 17:30:04 +09:00
f5bf41cf11 Fixed simple copy with nocpoyapi and modify flag in fdcache 2019-08-11 07:42:48 +00:00
f74c7407db Merge pull request #1118 from gaul/atoi
Prefer s3fs_strtoofft over atoi and strtol
2019-08-06 21:23:37 +09:00
433c04af26 Merge pull request #1116 from gaul/bodydata
Do not heap allocate BodyData
2019-08-06 21:08:02 +09:00
2e51a339a9 Merge pull request #1115 from gaul/hash-length
Use length from s3fs_HMAC256 for consistency
2019-08-06 20:49:22 +09:00
0411872dda Merge pull request #1121 from ggtakec/update_test
Added stats cache expire option for test
2019-08-06 20:32:48 +09:00
d8f1aef7be Added stats cache expire option for test 2019-08-06 10:55:38 +00:00
14d3e12103 Merge pull request #1114 from gaul/flush/return-value
Consume return value from FdEntity::Flush
2019-08-06 14:12:25 +09:00
fd13eb314b Merge pull request #1120 from ggtakec/osx_auto_cache
Added auto_cache option for test on osx
2019-08-06 13:31:23 +09:00
daba563a1c Added auto_cache option for test on osx 2019-08-06 02:44:18 +00:00
b79b0b1a92 Merge pull request #1119 from ggtakec/osx_direct_io
Added direct_io option for test on osx
2019-08-06 11:14:51 +09:00
01d4323b50 Merge pull request #1117 from gaul/retry
Increase test startup retries on Linux
2019-08-06 10:54:55 +09:00
dc85eda188 Added direct_io option for test on osx 2019-08-05 17:12:49 +00:00
ccf3e7bfa2 Prefer s3fs_strtoofft over atoi and strtol
The former propagates errors consistently.
2019-08-03 16:13:48 -07:00
d22acae9a3 Increase test startup retries on Linux
This matches the number of retries on macOS and allows Valgrind to
work.
2019-08-03 16:10:42 -07:00
7ecfba811e Do not heap allocate BodyData
Callers already manage lifetimes via Clear().
2019-08-03 15:50:46 -07:00
1e7330e499 Merge pull request #1113 from gaul/unused
Remove unused field
2019-08-04 01:31:56 +09:00
68475e5fcf Merge pull request #1112 from gaul/travis/macos
Upgrade to Xcode 9.2
2019-08-04 01:15:18 +09:00
8cc008c501 Merge pull request #1111 from gaul/test/read-external-object
Add test to read an externally created object
2019-08-03 22:36:34 +09:00
faaaf2ee3c Merge pull request #1110 from gaul/flags/noobj
Test enable_noobj_cache
2019-08-03 22:24:56 +09:00
3d42d0515d Merge pull request #1109 from gaul/lock-already-held
Pass lock_already_held state to DelStat
2019-08-03 22:13:22 +09:00
3d70e8966f Merge pull request #1108 from gaul/lock/diskspace
Always hold lock when accessing free_disk_space
2019-08-03 22:01:31 +09:00
6837cbfe06 Merge pull request #1107 from gaul/concurrency
Access FdEntity metadata while holding fdent_lock
2019-08-03 21:49:54 +09:00
a5c20175a1 Use length from s3fs_HMAC256 for consistency
EVP_MAX_MD_SIZE can range up to 64.  Found by Coverity.
2019-08-02 10:40:55 -07:00
43d1439420 Consume return value from FdEntity::Flush
Found via Coverity.
2019-08-02 10:01:06 -07:00
d8cf26bd50 Remove unused field
Found via clang.
2019-08-01 16:42:38 -07:00
c321c8c23f Add test to read an externally created object
References #890.
2019-08-01 16:12:51 -07:00
6227fce091 Upgrade to Xcode 9.2
This is the latest version supported by macOS 10.12.
2019-08-01 15:50:50 -07:00
aba8e6ccfa Test enable_noobj_cache 2019-08-01 12:39:11 -07:00
f528a86219 Pass lock_already_held state to DelStat 2019-08-01 11:07:56 -07:00
5b15c7c4e9 Always hold lock when accessing free_disk_space
Slightly reorder locks to avoid double locking.  Found via
ThreadSanitizer.
2019-07-30 08:36:54 -07:00
afd438d363 Access FdEntity metadata while holding fdent_lock
Create copies to avoid thread races.  Found via ThreadSanitizer.
Follows on to ecf13a8cb9.
2019-07-29 13:54:57 -07:00
80972aa33d Merge pull request #1106 from ggtakec/fix_filter
Fixed filter-suite-log.sh for on osx
2019-07-22 18:13:07 +09:00
520995a7e8 Merge pull request #1104 from gaul/sysconf
Eagerly initialize sysconf variables
2019-07-22 18:04:39 +09:00
5c3c6bff2f Fixed filter-suite-log.sh for on osx 2019-07-21 15:32:10 +00:00
fb937635f5 Eagerly initialize sysconf variables
Previously s3fs had races updating these shared variables.  Found via
ThreadSanitizer.
2019-07-17 09:08:13 -07:00
3ad1c95e86 Merge pull request #1103 from gaul/config/readwrite-timeout
Use consistent default for readwrite_timeout
2019-07-17 22:37:02 +09:00
2c4c78fd65 Merge pull request #1102 from gaul/test/concurrent-write
Add a test for concurrent writes
2019-07-17 22:24:45 +09:00
0afef077ed Merge pull request #1101 from gaul/gmtime
Avoid race when using thread-unsafe gmtime
2019-07-17 22:17:18 +09:00
80f598f439 Merge pull request #1099 from ggtakec/filter_log
Add log output filter script at test failure
2019-07-17 22:01:28 +09:00
bacd15714a Use consistent default for readwrite_timeout
Previously curl threads mutated this shared state without a lock.
Found via ThreadSanitizer.
2019-07-16 22:03:56 -07:00
5cb7a31c09 Add a test for concurrent writes 2019-07-16 21:57:43 -07:00
99aace4fc9 Avoid race when using thread-unsafe gmtime
Found via ThreadSanitizer.
2019-07-16 07:28:34 -07:00
c7f8f61d09 Change test_concurrency test 2019-07-15 15:58:54 -07:00
159cd2c682 Add log output filter script at test failure 2019-07-15 06:37:43 +00:00
513f41fddf Merge pull request #1097 from ggtakec/fix_lock
Add Lock() func parameter in RowFlush()
2019-07-15 11:56:21 +09:00
543aed2a32 Merge pull request #1096 from gaul/pthread/lock-checking
Expand error checking to all pthread_mutex_t
2019-07-15 11:43:56 +09:00
20ea96328c Merge pull request #1095 from gaul/intmax_t
Avoid narrowing time_t and off_t args in logging
2019-07-15 11:33:44 +09:00
007edb1773 Merge pull request #1090 from gaul/strtoofft
Implement s3fs_strtoofft via strtoll
2019-07-15 11:26:03 +09:00
f78bcc5229 Add Lock() func parameter in RowFlush() 2019-07-15 01:52:29 +00:00
43ec064fb9 Expand error checking to all pthread_mutex_t 2019-07-14 18:21:23 -07:00
ffac4c8417 Avoid narrowing time_t and off_t args in logging
This displays correct results on 32-bit platforms.
2019-07-14 17:02:36 -07:00
4adcd4a6c8 Implement s3fs_strtoofft via strtoll
This tightens error checking and aligns s3fs with known good behavior.
2019-07-14 15:15:06 -07:00
e936854493 Merge pull request #1094 from larsch/master
Fix multipart upload not setting curl options
2019-07-15 05:13:37 +09:00
850a813171 Merge pull request #1092 from liuyongqing/master
fix coredump caused by fd_manager_lock locking
2019-07-15 04:53:10 +09:00
5bbcd3b981 Merge pull request #1089 from gaul/null-dereference
Avoid null dereference
2019-07-15 04:17:10 +09:00
a337c32840 Merge pull request #1088 from gaul/clang-tidy/misplaced-const
Avoid misplaced const via removing unneeded typedef
2019-07-15 04:08:51 +09:00
d39e4e4b1f Merge pull request #1087 from gaul/clang-tidy/deprecated-headers
Prefer modern C headers
2019-07-15 03:50:15 +09:00
b51d60ef5e Merge pull request #1082 from gaul/locking/fixes
Add a missing lock to SetCtime
2019-07-15 03:38:53 +09:00
58037da061 Fix multipart upload not setting curl options 2019-07-14 14:09:37 +02:00
1eb266588e Add a missing lock to SetCtime
Also lock before log statements which touch member variables.
2019-07-13 17:53:38 -07:00
deb560067e Merge pull request #1085 from gaul/no-recusive-locks
Remove recursive locking
2019-07-14 01:14:32 +09:00
4e351c59e3 fix coredump caused by fd_manager_lock locking 2019-07-13 12:03:27 +08:00
eb597289cb Avoid null dereference
Found via clang-tidy.
2019-07-12 18:40:24 -07:00
6fd42d9fe4 Prefer modern C headers
Found and fixed via clang-tidy.
2019-07-12 03:50:59 -07:00
efff9c01a6 Avoid misplaced const via removing unneeded typedef
Found via clang-tidy.
2019-07-12 03:41:19 -07:00
a83d5baa90 Remove recursive locking
Recursive locking is frowned upon and is incompatible with
PTHREAD_MUTEX_ERRORCHECK.  Also clean up pthread_mutex_lock error
checking.
2019-07-10 12:39:00 -07:00
50d13255e4 Merge pull request #1081 from gaul/write-blocks-readdir
Break FdEntity locks into data and metadata
2019-07-11 03:40:26 +09:00
5195fa93fa Merge pull request #1071 from gaul/macos/xattr
Run xattr tests on macOS
2019-07-07 17:37:00 +09:00
e5e63d6ac3 Merge pull request #1067 from gaul/mismatched-free
Fix mismatched new[]/free
2019-07-07 16:55:07 +09:00
7a65a414c3 Merge pull request #1080 from gaul/xml/simplification
Add simple XML parsing wrapper
2019-07-07 16:44:18 +09:00
4a192ffdf9 Run xattr tests on macOS 2019-07-07 00:39:45 -07:00
944d21cabb Fix mismatched new[]/free
Found via Valgrind.
2019-07-07 00:36:48 -07:00
d267212289 Merge pull request #1079 from gaul/cppcheck/shadowing
Avoid shadowing variable in FdEntity::Open
2019-07-07 16:29:42 +09:00
58d8e5586a Merge pull request #1078 from gaul/multipart/2x
Issue multipart when object size exceeds part size
2019-07-07 16:21:22 +09:00
ce803daf4a Merge pull request #1077 from gaul/openssl/locking
Annotate OpenSSL locking functions as unused
2019-07-07 16:10:14 +09:00
9bf34e2fda Merge pull request #1076 from gaul/doc/man-help
Add documentation for use_session_token and use_rrs
2019-07-07 15:45:42 +09:00
52218d2ddb Merge pull request #1075 from gaul/fortify-source
Compile with FORTIFY_SOURCE
2019-07-07 15:38:08 +09:00
6bd1a7eac0 Merge pull request #1074 from gaul/clang-tidy
Configure clang-tidy target
2019-07-07 15:28:08 +09:00
6177d7b096 Merge pull request #1073 from gaul/deps/s3proxy
Upgrade to S3Proxy 1.6.2
2019-07-07 15:19:00 +09:00
3161bf4608 Merge pull request #1070 from gaul/bash/nounset
Prohibit pipeline failures
2019-07-07 15:10:53 +09:00
2349dafb98 Merge pull request #1069 from gaul/macos/sed
Use system sed on macOS
2019-07-07 15:00:48 +09:00
1cd58d7828 Merge pull request #1035 from gaul/test/flags
Individually test multiple s3fs flags
2019-07-07 14:41:15 +09:00
8aa06d621a Add documentation for use_session_token and use_rrs
Fixes #929.
2019-07-06 10:04:43 -07:00
ecf13a8cb9 Break FdEntity locks into data and metadata
Previously long-running data operations like RowFlush would block
metadata operations like GetStats and thus user readdir.  Fixes #928.
2019-07-05 23:12:24 -07:00
b8ff6a647e Add simple XML parsing wrapper
Also simplify check_region_error.
2019-07-05 17:39:09 -07:00
49110c671d Avoid shadowing variable in FdEntity::Open
Found via cppcheck 1.88.
2019-07-05 15:06:18 -07:00
febaf6849f Issue multipart when object size exceeds part size
Previously s3fs issued multipart uploads when the object size was
twice the part size.  Conjoining this with the part size was confusing
and s3fs should add a separate tunable for this if needed, similar to
singlepart_copy_limit.  Fixes #1058.
2019-07-05 12:14:56 -07:00
4893174652 Annotate OpenSSL locking functions as unused
OpenSSL 1.1.0 removed these and generates warnings with newer
versions.
2019-07-05 10:45:57 -07:00
5820c72092 Compile with FORTIFY_SOURCE
This can catch some classes of buffer overflows.
2019-07-04 10:20:26 -07:00
4f23f38583 Individually test multiple s3fs flags
Remove unneeded comments; single part limits ensure that the tests
exercise multipart code paths even with smaller files.
References #971.
2019-07-03 21:09:40 -07:00
bbfa91141a Configure clang-tidy target
Also fix nits.
2019-07-03 14:04:11 -07:00
f439c6382f Upgrade to S3Proxy 1.6.2
Notably this includes support for List Objects v2 which AWS CLI uses.
Release notes:

https://github.com/gaul/s3proxy/releases/tag/s3proxy-1.6.2
2019-07-03 10:37:26 -07:00
21321a9d96 Merge pull request #1065 from gaul/doc/ssl-verify-hostname
Document ssl_verify_hostname
2019-07-03 22:15:33 +09:00
f03b50fd13 Merge pull request #1063 from gaul/truncate-2nd-open-fd
Flush file when opening second fd
2019-07-03 21:14:03 +09:00
15a870f9d9 Merge pull request #1061 from gaul/fdpagelist/value
Make fdpage a value type in fdpage_list_t
2019-07-03 21:04:16 +09:00
9472ee4a01 Prohibit pipeline failures 2019-07-03 02:57:40 -07:00
1f1f824da7 Use system sed on macOS
This requires fewer developer customizations to work on macOS.
Requires some GNU workarounds.
2019-07-02 22:17:02 -07:00
f02105c346 Document ssl_verify_hostname
References #1064.
2019-07-02 10:26:29 -07:00
c596441f58 Flush file when opening second fd
Previously when s3fs had dirty local data and an application opened a
second fd it would remove the stat cache entry, query S3 for the size
which was still zero, then reinitialize FdEntry with this incorrect
size.  Instead flush local data to S3 so this query works.  It is
possible that a more involved patch could do this with a less
heavyweight approach but this requires changing open.  This does not
completely fix git clone but allows it to proceed further.  Also make
some cache methods const-correct.  References #839.
2019-07-02 01:12:09 -07:00
455e29cbea Make fdpage a value type in fdpage_list_t
This simplifies memory management.
2019-07-01 09:30:48 -07:00
511d223468 Merge pull request #1059 from gaul/casting
Fix casting warning on 32-bit
2019-07-01 22:26:14 +09:00
5324c1b588 Merge pull request #1055 from gaul/test/litter
Remove litter from test_concurrency
2019-07-01 22:10:57 +09:00
554ea49294 Merge pull request #1051 from gaul/log/flags
Log flags as hexadecimal
2019-07-01 21:36:17 +09:00
d7f77a6282 Fix casting warning on 32-bit 2019-06-29 20:57:42 -07:00
048aea1151 Remove litter from test_concurrency 2019-06-26 20:29:27 -07:00
f1ad626b46 Log flags as hexadecimal 2019-06-24 16:13:07 -07:00
a78d8d1da4 Merge pull request #1049 from gaul/external-modication
Remove cache file when object time differs
2019-06-24 00:51:54 +09:00
fbebc6fa57 Merge pull request #1048 from gaul/log/curl
Emit older curl warnings only once
2019-06-24 00:42:44 +09:00
c18fc901c4 Merge pull request #1045 from gaul/test/umount-s3fs
Correct macOS integration test umount
2019-06-23 23:02:46 +09:00
245f14c8c1 Merge pull request #1041 from gaul/doc/typo
Fix singlepart_copy_limit default
2019-06-23 22:57:43 +09:00
d732eef776 Merge pull request #1039 from gaul/off_t
Convert file offsets from size_t to off_t
2019-06-23 22:51:04 +09:00
56b184fd0c Merge pull request #1032 from gaul/man/env
Add environment variables to man page
2019-06-23 22:42:39 +09:00
9e5eaad79b Remove cache file when object time differs
Check the modification times to determine whether an object has
updated.  This relies on low clock skew between s3fs and the S3
server; a more robust approach could use the ETag.  Fixes #1047.
2019-06-22 19:09:00 -07:00
738eaadcbf Emit older curl warnings only once
This makes Travis logs actually readable.
2019-06-22 10:01:20 -07:00
1cf3d2452e Correct macOS integration test umount
Previously errexit could prevent this from succeeding.
2019-06-19 11:01:32 -07:00
670dce6f4a Merge pull request #1036 from gaul/travis/macos
Do not update Homebrew in macOS builder
2019-06-18 22:24:36 +09:00
07cfdcf205 Fix singlepart_copy_limit default
Follows on to c5ebf5d328.
2019-06-15 17:38:14 -07:00
15b7450713 Convert file offsets from size_t to off_t
The latter is 64-bits on 32-bit platforms when specifying
-D_FILE_OFFSET_BITS=64.  This allows early Raspberry Pis to use files
larger than 2 GB.  It also cleans up some ugly casting.  Fixes #620.
Fixes #656.
2019-06-15 17:05:37 -07:00
272e0d3d46 Do not update Homebrew in macOS builder
This takes 5 minutes to run and can cause Travis timeouts.
References #1035.
2019-06-12 18:17:56 -07:00
8d8a2a66e5 Add environment variables to man page
Also fix typo in AWS credentials.
2019-05-15 18:49:18 +07:00
befc2e9e6f Merge pull request #1025 from gaul/nocopyapi
Update ctime during nocopyapi operations
2019-05-02 17:55:42 +09:00
059ab1f0f4 Update ctime during nocopyapi operations
Follows on to 2c43b1e12b.  Fixes #971.
2019-04-30 18:59:51 +09:00
f2fe1738cd Merge pull request #1021 from michallula/master
fix issue with aws session token provided inside ~/.aws/credentials file
2019-04-28 11:03:48 +09:00
0d4847596e fix issue with aws session token provided inside ~/.aws/credentials file 2019-04-25 14:29:35 +02:00
8e86ef1634 Merge pull request #1015 from gaul/c++03
Remove uses of std::map::at
2019-04-22 23:01:29 +09:00
a32a05962e Merge pull request #1014 from gaul/macro
Prefer simple over compound statements in macros
2019-04-22 22:49:23 +09:00
a7e81fda9b Merge pull request #1012 from gaul/doc/markdown
Address markdownlint warnings
2019-04-22 22:39:55 +09:00
9e4f9d4bdc Remove uses of std::map::at
This provides compatibility with C++03 and removes duplicate lookups.
2019-04-18 16:06:59 +09:00
0677a096a9 Prefer simple over compound statements in macros
This prohibits missing semicolons.
2019-04-17 21:46:24 +09:00
381835e2a9 Merge pull request #1008 from michallula/master
AWS session token support
2019-04-17 17:52:08 +09:00
af070fa3de Address markdownlint warnings 2019-04-17 08:09:31 +09:00
f9cd43b684 add session token support 2019-04-16 16:53:05 +02:00
7095787f1f Merge pull request #1011 from gaul/doc/man
Make man page and --help more consistent
2019-04-16 23:07:17 +09:00
4ca336aed0 Merge pull request #1003 from gaul/doc/installation
Standardize installation section
2019-04-16 22:30:51 +09:00
8a18806a57 Make man page and --help more consistent
Mostly small fixes but also some reordering.  References #929.  Found
via:

diff -u <(man --no-hyphenation doc/man/s3fs.1 | tr -s ' ' '\n' | sed '/^-o$/d' ) <(src/s3fs --help | tr -s ' ' '\n' | sed '/^-$/d')
2019-04-14 14:34:24 +09:00
e5e124b9aa Merge pull request #1006 from gaul/shellcheck
Address shellcheck errors
2019-04-09 23:39:11 +09:00
090ac7a8a0 Merge pull request #1005 from gaul/travis/simplify
Remove custom cppcheck from ppc64le Travis config
2019-04-09 23:29:06 +09:00
97af471aa6 Remove custom cppcheck from ppc64le Travis config 2019-04-09 21:25:58 +09:00
0176fc712b Address shellcheck errors 2019-04-09 21:11:31 +09:00
c426c896d0 Standardize installation section
Sort Linux distributions and simplify/standardize grammar.
2019-04-09 07:52:54 +09:00
0a99470369 Merge pull request #1002 from gaul/sse-c
Correctly calculate MD5 hash for SSE-C keys
2019-04-09 00:17:12 +09:00
cd280d8702 Merge pull request #1001 from gaul/missing-braces
Add missing braces
2019-04-08 23:55:02 +09:00
b1bade37d8 Merge pull request #1000 from ggtakec/master
Modified to discard _netdev option etc
2019-04-08 23:43:02 +09:00
005c186e1b Merge pull request #998 from gaul/doc/compilation
Move compilation instructions to separate file
2019-04-08 23:32:54 +09:00
6f8ecb28c5 Correctly calculate MD5 hash for SSE-C keys
Previously s3fs calculated the strlen of a binary input instead of
using the stored length.  This yielded IO errors when interacting with
SSE-encrypted objects.  Fixes #696.
2019-04-08 21:49:42 +09:00
4c28eb2a78 Move compilation instructions to separate file
Most users should use distribution packages and expert users can
consult this file.  References #991.
2019-04-08 15:56:46 +09:00
042332bcec Add missing braces
Found via clang-tidy.  Also fix errant indentation.
2019-04-07 23:12:27 +09:00
071cd0f849 Modified to discard _netdev option etc 2019-04-07 11:51:55 +00:00
d7bb834bcb Merge pull request #999 from gaul/malloc
Prefer new over malloc
2019-04-07 20:21:58 +09:00
9b437fc1fe Merge pull request #997 from gaul/doc/http
Prefer HTTPS links in documentation where possible
2019-04-07 19:44:38 +09:00
6f6a67807b Prefer new over malloc
The former cannot return NULL and will allow use of scoped pointers.
2019-04-07 16:54:24 +09:00
e5785d4690 Prefer HTTPS links in documentation where possible
This also corrects a test URL which was HTTPS in practice.
2019-04-05 17:31:06 +09:00
a4ce54d615 Merge pull request #995 from jaygooby/master
Work with filenames that include spaces
2019-04-02 23:17:39 +09:00
ddbcec5c96 Work with filenames that include spaces
• Simplified the stat generation line (single exec using only stat)
• Quote variables so that the cache directory can also include spaces
• while/read loop to handle spaces in cached files
  (IFS was causing problems when all the files were saved into a single variable)
2019-04-02 10:35:25 +01:00
7cbb4c958b Merge pull request #994 from gaul/doc/nits
Add commas to see also
2019-03-31 07:27:44 +09:00
6c5adbb9af Add commas to see also 2019-03-30 23:25:58 +09:00
4db6e1a10a Merge pull request #993 from ggtakec/test
Fixed a bug about overwrite metadata at updating directory stats
2019-03-30 01:18:48 +09:00
ea517c80a4 Fixed a bug about overwrite metadata at updating directory stats 2019-03-29 15:30:30 +00:00
9f6ed6c08e Merge pull request #992 from ggtakec/master
Added see also section to man page
2019-03-29 09:23:18 +09:00
b1ddb483a4 Added see also section to man page 2019-03-28 23:59:19 +00:00
17352ef4fd Merge pull request #987 from ggtakec/master
Support undefined CURLoption in libcurl library used in build
2019-03-22 20:34:48 +09:00
71766039ff Support undefined CURLoption in libcurl library used in build 2019-03-22 10:47:42 +00:00
c607c9be58 Merge pull request #985 from ggtakec/master
Fixed configure.ac about abuses AC_CHECK_FILE
2019-03-22 15:19:04 +09:00
df604e50fb Fixed configure.ac about abuses AC_CHECK_FILE 2019-03-22 05:22:23 +00:00
876662ff89 Merge pull request #982 from gaul/cppcheck/find-first-of
Simplify string comparison
2019-03-22 13:59:45 +09:00
058706014b Simplify string comparison
Found via newer cppcheck.
2019-03-14 22:19:33 +09:00
99ec09f13a Merge pull request #978 from ggtakec/master
Updated ChangeLog and configure.ac etc for release 1.85
2019-03-11 21:32:25 +09:00
4a011d87e0 Updated ChangeLog and configure.ac etc for release 1.85 2019-03-11 11:53:57 +00:00
c6edc2cd8f Merge pull request #977 from gaul/readme/homebrew
Make macOS instructions consistent with others
2019-03-11 20:26:26 +09:00
cc196bfdf0 Make macOS instructions consistent with others 2019-03-11 14:36:36 +09:00
895d5006bb Merge pull request #975 from ggtakec/master
Fixed ref-count when error occurred.
2019-03-10 15:09:09 +09:00
62dcda6a56 Fixed ref-count when error occurred. 2019-03-10 06:04:19 +00:00
cbf072bc55 Merge pull request #967 from gaul/reference-count
Increase FdEntity reference count when returning
2019-03-10 14:27:10 +09:00
1b4d2a32d2 Merge pull request #974 from ggtakec/master
Changed the description order of man page options
2019-03-10 13:43:51 +09:00
b71c90bbe1 Changed the description order of man page options 2019-03-10 04:32:10 +00:00
80344aafd3 Merge pull request #972 from gaul/readme/amazon-linux
Add instructions for Amazon Linux
2019-03-10 13:11:04 +09:00
b5ca400500 Merge pull request #970 from gaul/nocopyapi
Remove from file from stat cache during rename
2019-03-10 12:56:04 +09:00
2e89439120 Merge pull request #969 from gaul/typo/lazy
Fix lazy typo
2019-03-10 12:40:59 +09:00
555410386c Add instructions for Amazon Linux 2019-03-09 22:25:06 +09:00
08b132ddb9 Remove from file from stat cache during rename
This addresses failures with test_rename_before_close when using
nocopyapi.  Note that test_update_time still fails.
2019-03-09 17:53:35 +09:00
1e86cc643d Fix lazy typo 2019-03-09 17:46:02 +09:00
f53503438c Increase FdEntity reference count when returning
Previously s3fs had a race condition where one client could delete
FdEntity that another client was using.  Add a simple concurrent test
which previously failed but now succeeds.  Fixes #964.
2019-03-09 15:55:04 +09:00
0d43d070cc Merge pull request #965 from ggtakec/fix_multi_x
Improvement of curl session pool for multipart
2019-02-27 22:44:25 +09:00
0791fdca2a Merge pull request #960 from kristjanvalur/wtf8
Wtf8
2019-02-27 21:21:38 +09:00
6e8678d5e3 remove lines that wer accidentally duplicated 2019-02-25 16:02:01 +00:00
10d9f75366 Improvement of curl session pool for multipart
Improvement of curl session pool for multipart(2)

Improvement of curl session pool for multipart(3)
2019-02-25 14:46:24 +00:00
77993e607e Merge pull request #961 from gaul/cppcheck
Work around cppcheck warnings
2019-02-24 11:24:28 +09:00
74d8671e54 Work around cppcheck warnings
Follows on to eeb839242b.
2019-02-20 21:55:41 +09:00
4c41eac29c fix documentation and man page 2019-02-20 11:24:29 +00:00
3c97c1b251 merged main 2019-02-19 10:53:00 +00:00
84c671a81a fix indentation 2019-02-19 10:37:43 +00:00
f336bdebcc add command line flag and documentation 2019-02-19 10:32:37 +00:00
e5b8377202 fix comments and code 2019-02-19 10:32:10 +00:00
4f42f4ab0c Enable s3fs encoding and decoding in the fuse interface 2019-02-18 13:36:48 +00:00
11b385820d more robust wtf8 encoding 2019-02-18 12:27:44 +00:00
f1a9eaee54 Merge pull request #958 from gaul/readme/inotify
Document lack of inotify support
2019-02-17 23:28:24 +09:00
ffee8d5f39 Merge pull request #959 from ggtakec/master
Fixed code for latest cppcheck error on OSX
2019-02-17 23:19:17 +09:00
eeb839242b Fixed code for latest cppcheck error on OSX 2019-02-17 13:59:11 +00:00
f7760976a5 Document lack of inotify support
References #45.
2019-02-17 19:45:08 +09:00
ca2d1d873d Adding utility functions to convert invalid utf8 to wtf8 encoding
This is to deal with windows clients who pass in cp1252 as if it
were utf8
2019-02-15 15:57:03 +00:00
951761ee2c Merge pull request #951 from ggtakec/master
Added a non-interactive option to utility mode
2019-02-11 03:03:01 +09:00
231fd001d9 Added a non-interactive option to utility mode
Rebase for resolving conflicts

Deleted interactive mode on utility mode

Fixed minor mistakes
2019-02-10 17:36:18 +00:00
e00afa8128 Merge pull request #957 from gaul/deps/s3proxy-1.6.1
Upgrade to S3Proxy 1.6.1
2019-02-10 23:32:13 +09:00
e9297f39ea Upgrade to S3Proxy 1.6.1
Notably, this improve performance when listing objects using the
filesystem backend, allowing new tests like expanding large tar files.
Release notes:

https://github.com/gaul/s3proxy/releases/tag/s3proxy-1.6.1
2019-02-06 17:06:43 -08:00
314dc5a398 Merge pull request #955 from gaul/clang-tidy/misc
Address miscellaneous clang-tidy warnings
2019-02-06 21:21:54 +09:00
e07cb020cc Merge pull request #954 from gaul/clear-iter
Clear containers instead of individual erases
2019-02-06 21:12:36 +09:00
9f79b9e0da Merge pull request #953 from gaul/readme/s3ql
Update s3ql link
2019-02-06 21:03:28 +09:00
e87e40b3b4 Address miscellaneous clang-tidy warnings
Also add configuration with suppressions.
2019-02-04 22:58:40 -08:00
f0f95478ec Update s3ql link 2019-02-04 21:03:46 -08:00
bd66b57ad3 Merge pull request #952 from gaul/multipart/failed
Automatically abort failed multipart requests
2019-02-04 22:19:27 +09:00
a1d3ff9766 Automatically abort failed multipart requests
This can avoid dangling parts.  However, many transfers fail due to
network errors so we still need other mechanisms to handle these
parts.
2019-02-03 10:29:20 -08:00
7f61a947c2 Merge pull request #950 from ggtakec/master
Added S3FS_MALLOC_TRIM build switch
2019-02-03 17:23:09 +09:00
4d0bef1e90 Clear containers instead of individual erases
This has O(n) runtime instead of O(n log n).
2019-02-02 23:58:43 -08:00
960823fb40 Added S3FS_MALLOC_TRIM build switch 2019-02-03 07:36:17 +00:00
c04e8e7a9d Merge pull request #949 from gaul/503-slow-down
Implement exponential backoff for 503
2019-02-03 15:19:28 +09:00
fb6debd986 Merge pull request #948 from gaul/too-many-parts
Add logging for too many parts
2019-02-03 14:55:54 +09:00
d8185a25aa Merge pull request #946 from gaul/async/completed-tids
Simplify async request completion code
2019-02-03 14:08:49 +09:00
53337a0a28 Merge pull request #944 from gaul/utility-mode
Repair utility mode
2019-02-03 13:59:56 +09:00
ae51556d04 Merge pull request #943 from gaul/hard-link
Return not supported when hard linking
2019-02-03 12:45:21 +09:00
b3de9195a7 Merge pull request #942 from gaul/c++03
Ensure s3fs compiles with C++03
2019-02-03 12:35:49 +09:00
055ecf6ea7 Merge pull request #940 from gaul/parallel-multipart-copy
Copy parts in parallel
2019-02-03 11:44:15 +09:00
c603680e02 Merge pull request #939 from gaul/stringstream-specific
Prefer specific [io]stringstream where possible
2019-02-03 11:06:57 +09:00
814aadd7e3 Merge pull request #938 from gaul/clang-tidy/redundant-void
Remove unneeded void parameter
2019-02-03 10:57:56 +09:00
dce63d1529 Merge pull request #937 from gaul/malloc-trim
Disable malloc_trim
2019-02-03 10:48:15 +09:00
8ff05d8e38 Implement exponential backoff for 503
Amazon returns SlowDown when overloaded.  Also return ENOTSUP for 501
and immediately return EIO for 500 instead of retrying.  Fixes #603.
2019-02-02 00:03:50 -08:00
dfa84b82a8 Add logging for too many parts
References #610.
2019-02-01 19:34:26 -08:00
6ac8618381 Ensure s3fs compiles with C++03 2019-02-01 08:33:59 -08:00
8c527c3616 Simplify async request completion code
Workers now notify the master thread when they complete, unifying the
Linux and macOS code paths.  This also avoids excessive
pthread_tryjoin_np calls.  Follows on to
88cd8feb05.
2019-01-31 22:55:23 -08:00
54a074647e Repair utility mode
This deinitialized S3fsCurl twice and incorrectly calculated V4
signatures.
2019-01-31 18:45:39 -08:00
c5ebf5d328 Copy parts in parallel
S3 can copy multipart much faster than single part due to IO
parallelization.  Renaming a 4 GB file reduces from 72 to 20 seconds
with bigger gains with larger files.
2019-01-31 10:21:39 -08:00
43c6ef560e Return not supported when hard linking
This is more correct than permission denied.
2019-01-30 16:43:04 -08:00
3076abc744 Disable malloc_trim
This avoids walking the entire heap multiple times for complex
operations like readdir.  This does not entirely eliminate the
observed performance regression but does dramatically reduce s3fs CPU
usage.  References #935.  Fixes #936.
2019-01-29 15:29:07 -08:00
07636c8a8d Prefer specific [io]stringstream where possible
These better communicate intent and are slightly more efficient.
2019-01-29 10:44:33 -08:00
35d55ee513 Remove unneeded void parameter
This is implicit in C++.  Found and fixed via clang-tidy.
2019-01-28 23:22:27 -08:00
a442e843be Merge pull request #934 from ggtakec/master
Checked and corrected all typo
2019-01-27 21:33:16 +09:00
c0cf90cf8b Checked and corrected all typo 2019-01-27 12:04:29 +00:00
3b1cc3b197 Merge pull request #933 from gaul/cache/remove-mirror-path
Remove mirror path when deleting cache
2019-01-27 16:15:49 +09:00
a0c1f30ae7 Merge pull request #932 from gaul/autolock
Prefer AutoLock for synchronization
2019-01-27 15:59:18 +09:00
8822a86709 Merge pull request #931 from gaul/doc/typo
Correct sigv2 typo
2019-01-27 15:48:24 +09:00
98f397de0e Merge pull request #930 from gaul/doc/md5-multipart
Correct enable_content_md5 docs
2019-01-27 15:36:56 +09:00
fd4d23f8f7 Merge pull request #926 from kzidane/master
Accept paths with : in them
2019-01-27 15:23:24 +09:00
4820f0a42b Merge pull request #925 from gaul/clang-tidy/delete-null
Remove redundant null checks before delete
2019-01-27 15:15:31 +09:00
807a618cf7 Merge pull request #924 from gaul/clang-tidy/empty
Prefer empty over size checks
2019-01-27 15:04:52 +09:00
a93e500b44 Remove mirror path when deleting cache
Fixes #827.
2019-01-25 18:10:03 -08:00
92d3114584 Prefer AutoLock for synchronization
This simplifies the code and fixes an issue with unlocked access.
Also use a recursive lock for StatCache to avoid races between
lock..unlock..lock sequences.
2019-01-25 15:28:41 -08:00
5062d6fbd9 Correct sigv2 typo 2019-01-25 14:30:30 -08:00
7d14ebaf09 Correct enable_content_md5 docs
Both S3fsCurl::PutRequest and S3fsCurl::UploadMultipartPostSetup can
calculate and send Content-MD5 to the server.  Remove spurious comment
about large files and make man page and help consistent.
References #929.
2019-01-25 14:27:52 -08:00
cd794a6985 Accept paths with : in them 2019-01-23 14:56:25 -05:00
84b421d6ef Prefer empty over size checks
Found and fixed via clang-tidy.
2019-01-23 11:30:28 -08:00
8316da5bbe Remove redundant null checks before delete
Found by clang-tidy.
2019-01-23 11:25:25 -08:00
fa287aeef7 Merge pull request #923 from ggtakec/master
Reverted automatic region change and changed messages
2019-01-23 23:00:31 +09:00
caaf4cac55 Reverted #912(Automatic region change) and added message 2019-01-23 13:23:03 +00:00
010276ceab Merge pull request #921 from gaul/clang-tidy/redundant-string-init
Remove redundant string initializations
2019-01-23 19:44:59 +09:00
f219817eb3 Merge pull request #920 from gaul/clang-tidy/string-copy
Remove unnecessary string copies
2019-01-23 19:30:55 +09:00
d487348d21 Merge pull request #919 from gaul/test/mv-nonempty-dir
Add test for mv non-empty directory
2019-01-23 19:21:12 +09:00
eb0b29708f Merge pull request #918 from gaul/overwrite-file-range
Load tail range during overwrite
2019-01-23 19:12:23 +09:00
877842a720 Merge pull request #917 from gaul/readme/aws-cli
Reference better-known AWS CLI for compatibility
2019-01-23 18:38:08 +09:00
1fc25e8c3f Remove redundant string initializations
Found and fixed via clang-tidy.
2019-01-22 23:16:37 -08:00
61ecafd426 Remove unnecessary string copies
Found via clang-tidy.
2019-01-22 23:09:37 -08:00
79bd3441eb Add test for mv non-empty directory 2019-01-22 22:13:17 -08:00
5f5da4b2cb Load tail range during overwrite
Previously s3fs experienced data loss when writing to the middle of a
file.  Corrupt files would have the expected data from 0..offset+size
but unexpected NUL bytes from offset+size..EOF.  References #808.
2019-01-22 22:02:40 -08:00
dede19d8c0 Reference better-known AWS CLI for compatibility 2019-01-21 17:32:57 -08:00
fada95f58e Merge pull request #914 from gaul/readdir/head-of-line
Issue readdir HEAD requests without batching
2019-01-21 22:10:50 +09:00
014b8c5982 Merge pull request #913 from gaul/assert
Prefer abort over assert(false)
2019-01-21 21:56:41 +09:00
46d79c5bc2 Issue readdir HEAD requests without batching
Previously s3fs would issue a batch of HEAD requests and wait for all
to succeed before issuing the next batch.  Now it issues the first
batch and only waits for a single call to succeed before issuing the
next call.  This can improve performance when one call lags due to
network errors.  I measured 25% improvement with the same level of
parallelism.  This commit also reparents parallelism knobs for
consistency.  Follows on to 88cd8feb05.
Fixes #223.
2019-01-20 18:07:22 -08:00
40ba3b44a1 Prefer abort over assert(false)
The compiler can remove the latter when compiled with NDEBUG which may
cause unintended control flow.
2019-01-20 12:30:27 -08:00
beadf95975 Merge pull request #912 from ggtakec/master
Automatic region change made possible other than us-east-1(default)
2019-01-20 20:13:07 +09:00
2887f8916b Automatic region change made possible other than us-east-1(default) 2019-01-20 10:51:49 +00:00
0c9a8932f7 Merge pull request #911 from ggtakec/master
Added detail error message when HTTP 301/307 status
2019-01-20 19:31:04 +09:00
ac72431195 Added detail error message when HTTP 301/307 status 2019-01-20 10:07:58 +00:00
2a7877beff Merge pull request #910 from ggtakec/master
Added a missing extension to .gitignore, and formatted dot files
2019-01-20 18:38:37 +09:00
7a56459103 Added a missing extension to .gitignore, and formatted dot files 2019-01-20 09:18:40 +00:00
5292fa74d1 Merge pull request #909 from ggtakec/master
Ignore after period character of floating point in x-amz-meta-mtime
2019-01-20 17:58:55 +09:00
f2184e34dd Ignore after period character of floating point in x-amz-meta-mtime 2019-01-20 08:28:06 +00:00
1d4867830b Merge pull request #908 from ggtakec/master
Added an error message when HTTP 301 status
2019-01-20 16:59:43 +09:00
36a4903843 Added an error message when HTTP 301 status 2019-01-20 07:17:40 +00:00
c83a3e67c9 Merge pull request #885 from LutzFinsterle2019/master
Update s3fs_util.cpp for correspondence of Nextcloud contype
2019-01-20 15:32:58 +09:00
05014c49c8 Merge pull request #906 from gaul/doc/https
Prefer HTTPS links where possible
2019-01-20 15:10:51 +09:00
aa69107165 Merge pull request #905 from gaul/clang-tidy/redundant
Fix comparison in s3fs_strtoofft
2019-01-20 15:01:40 +09:00
d373b0eca3 Merge pull request #904 from gaul/clang-tidy/c-str
Remove unnecessary calls to std::string::c_str
2019-01-20 14:13:46 +09:00
6aa40b2747 Merge pull request #903 from gaul/clang-tidy/find_char
Prefer find(char) over find(const char *)
2019-01-20 14:05:06 +09:00
34c3bfe408 Merge pull request #902 from gaul/clang-tidy/pass-by-value
Avoid pass-by-value when not necessary
2019-01-20 13:45:44 +09:00
6ac56e722d Merge pull request #901 from gaul/clang-tidy/leaks
Plug memory leaks
2019-01-20 12:41:08 +09:00
61dc7f0a70 Merge pull request #900 from gaul/leak
Plug memory leak
2019-01-20 12:30:31 +09:00
9f000957dd Merge pull request #899 from gaul/response-code
Tighten up HTTP response code check
2019-01-20 11:16:23 +09:00
b2141313e2 Merge pull request #898 from gaul/rename-before-close
Flush file before renaming
2019-01-20 10:13:20 +09:00
aa9bd1fa3c Prefer HTTPS links where possible
Fix a few stale links as well.
2019-01-18 11:09:08 -08:00
5a2dc03a1c Fix comparison in s3fs_strtoofft
Also backfill unit tests.  Document limitations.  Found via
clang-tidy.
2019-01-17 22:59:25 -08:00
508fafbe62 Remove unnecessary calls to std::string::c_str
Found via clang-tidy.
2019-01-17 22:05:16 -08:00
e29548178b Prefer find(char) over find(const char *)
The former can be faster.  Found via clang-tidy.
2019-01-17 20:24:24 -08:00
ab2f36f202 Plug memory leaks
Found via clang-tidy.
2019-01-17 18:54:34 -08:00
b8c9fcfd70 Avoid pass-by-value when not necessary
This requires unnecessary memcpy.  Found via clang-tidy.
2019-01-17 18:22:11 -08:00
58ce544e83 Plug memory leak
Previously this appended to an empty list, zeroed the list, then
appended to the list.  Instead zero the list first and then append.
This also enables sending Content-MD5 which can eagerly detect
transmission errors.  Found via Valgrind.
2019-01-17 16:24:34 -08:00
e98ce36301 Tighten up HTTP response code check
Previously s3fs considered 3xx codes as successful.  When writing an
object to a misconfigured region, s3fs did not propagate the 301 as a
write error to the client.  References #693.
2019-01-17 15:04:59 -08:00
6401b4ae92 Flush file before renaming
Previously s3fs could copy the zero-byte stub object without including
any pending writes.  Fixes #145.
2019-01-17 12:05:10 -08:00
25b49e1a2e Merge pull request #894 from gaul/default-mode
Default uid/gid/mode when object lacks permissions
2019-01-16 18:48:54 +09:00
c7def35b54 Merge pull request #895 from gaul/bucket-name-dot
Emit more friendly error for buckets with dots
2019-01-16 18:39:47 +09:00
ddba1c63c5 Merge pull request #893 from gaul/ctime
Store and retrieve file change time
2019-01-16 18:30:15 +09:00
c512516e14 Emit more friendly error for buckets with dots
These fail SSL certificate checks due to the *.s3.amazon.com wildcard.
Fixes #284.
2019-01-14 18:47:36 -08:00
2c43b1e12b Store and retrieve file change time
This introduces a new header with the change time; existing objects
will report modification time.  Fixes #771.
2019-01-14 10:05:11 -08:00
b68d97c6bf Merge pull request #892 from gaul/test/xattr
Repair xattr tests
2019-01-14 21:26:46 +09:00
f1757e4343 Merge pull request #888 from gaul/readme
Add Server Fault to FAQs
2019-01-14 21:17:06 +09:00
e2d5641d99 Default uid/gid/mode when object lacks permissions
This addresses a common use case when interacting with objects from
both s3fs and other S3 tools.  Fixes #890.
2019-01-13 21:57:23 -08:00
523fe1e309 Repair xattr tests
These did not run due to missing use_xattr flag and Travis
misconfiguration.
2019-01-13 18:54:16 -08:00
c985b5e4d0 Corrected Comment to C++ style 2019-01-12 10:19:48 +01:00
786f1a8fc7 Add Server Fault to FAQs
Also correctly format Stack Overflow.
2019-01-10 11:17:32 -08:00
18cb2e2662 Update s3fs_util.cpp
Sorry for answering late, have been busy lately.
The comment is: "Nextcloud stores Directory objects with this mime type when mounting a Bucket as external Storage"
2019-01-10 07:44:36 +01:00
743c706b0a Update s3fs_util.cpp
Nextcloud Compatibility in directory mime-types
2019-01-07 07:41:27 +01:00
4ed0e5f35a Merge pull request #882 from earlchew/issue-817
[curl] Assume long encryption keys are base64 encoded
2019-01-06 17:29:04 +09:00
fd6b37d3da Merge pull request #877 from gaul/aws/credentials
Check arguments and environment before .aws/creds
2019-01-06 17:03:11 +09:00
56e24de0d4 Merge pull request #870 from gaul/typos
Correct typos in command-line parsing
2019-01-06 16:21:46 +09:00
2780043a7d Merge pull request #856 from gaul/doc/icon
Add icon for s3fs
2019-01-06 15:54:24 +09:00
54c9e48bb7 Merge pull request #874 from gaul/cppcheck-1.86
Address cppcheck 1.86 errors
2019-01-06 15:20:28 +09:00
ed5795eead [curl] Assume long encryption keys are base64 encoded
Correct tabs and whitespace.

Signed-off-by: Earl Chew <earl_chew@yahoo.com>
2019-01-05 21:08:41 +00:00
3d225163f8 Correct typos in command-line parsing
Also fix stray macOS references.  References #869.
2019-01-02 14:40:57 -08:00
0569cec3ea Check arguments and environment before .aws/creds
Fixes #857.  Fixes #864.
2018-12-20 15:51:32 -08:00
a2f8ac535e Address cppcheck 1.86 errors
Lifetime, shadowing, and unused variables.  Found via the Travis macOS
builder.
2018-12-20 14:56:31 -08:00
29355d75b0 Add icon for s3fs
This is suitable for the s3fs-fuse organization.
2018-12-15 17:12:28 -08:00
d9e89deef6 Merge pull request #865 from orozery/multihead_warning_check
fix multihead warning check
2018-11-29 20:53:47 +09:00
6b051eac47 Merge pull request #866 from Basavaraju013/master
Multi-arch support for ppc64le
2018-11-29 20:37:02 +09:00
da997de918 Merge pull request #861 from mcgitty/patch-1
Add 'profile' option to command line help.
2018-11-29 20:15:01 +09:00
d97094fb8d Multi-support for ppc64le 2018-11-28 05:15:09 -06:00
b91fc5409e fix multihead warning check 2018-11-28 09:54:02 +02:00
3c970646d1 Add 'profile' option to command line help. 2018-11-19 08:26:23 -08:00
a92668ae78 Merge pull request #859 from gaul/upload-remove-batching
Upload S3 parts without batching
2018-11-18 22:27:20 +09:00
88cd8feb05 Upload S3 parts without batching
Previously s3fs would issue a batch of uploads and wait for all to
succeed before issuing the next batch.  Now it issues the first batch
and only waits for a single part to succeed before uploading the next
part.  This can improve performance when one part lags due to network
errors.  Fixes #183.
2018-11-16 18:32:38 -08:00
91c16f826a Merge pull request #855 from gaul/readme/stackoverflow
Include StackOverflow in FAQs
2018-11-14 22:32:10 +09:00
d4d60ff315 Include StackOverflow in FAQs 2018-11-13 22:19:17 -08:00
e8033f96de Merge pull request #853 from gaul/readme-tilde
Replace ~ with ${HOME} in examples
2018-11-11 11:47:44 +09:00
5fba542a29 Merge pull request #852 from gaul/aws-credentials-file
Allow credentials from ${HOME}/.aws/credentials
2018-11-11 11:37:38 +09:00
44de3ffa05 Merge pull request #851 from gaul/list-object-max-keys
Correctly compare list_object_max_keys
2018-11-11 11:26:31 +09:00
2efa6df028 Merge pull request #849 from gaul/readme
Correct typo
2018-11-11 11:17:05 +09:00
9e530c86ae Allow credentials from ${HOME}/.aws/credentials
This matches the configuration from popular tools like AWS CLI and
allows multiple profile names via -o profile=name.  The existing
credential mechanisms continue to work.  Fixes #822.
2018-11-04 17:47:07 -08:00
95857733a1 Replace ~ with ${HOME} in examples
Several of these do not work since the shell does not replace ~ in the
middle of a token, e.g., -o passwd=~/.passwd .  Replace all of them
for consistency.  Fixes #836.
2018-11-04 17:45:16 -08:00
664f910083 Correctly compare list_object_max_keys
Previously this did not allow an argument.  Fixes #843.
References #793.
2018-11-04 10:49:35 -08:00
735e4b0848 Correct typo 2018-10-29 21:42:48 -07:00
e8d76a6f58 Merge pull request #840 from juliogonzalez/macOS
Replace all mentions to MacOS X to macOS
2018-10-28 20:33:51 +09:00
0a6926be54 Merge pull request #835 from juliogonzalez/generic-compilation
Make the compilation instructions generic
2018-10-28 20:00:21 +09:00
830a971bde Replace all mentions to MacOS X to macOS 2018-10-14 23:23:19 +02:00
4779d14d7d Make the compilation instructions generic 2018-10-08 22:27:01 +02:00
8929a27a24 Merge pull request #834 from juliogonzalez/issue-improvements
Improve template for issues
2018-10-09 00:37:20 +09:00
eea624c171 Merge pull request #833 from juliogonzalez/doc
New installation instructions for Fedora >= 27 and CentOS7
2018-10-09 00:05:36 +09:00
cdaf4a9674 Merge branch 'master' into doc 2018-10-08 23:56:20 +09:00
6fe92d5ed6 Merge pull request #832 from gaul/hex
Simplify hex conversion
2018-10-08 23:03:42 +09:00
8649a68766 Merge pull request #831 from JoohnSF/onezone_ia_support
Add support for storage class ONEZONE_IA.
2018-10-08 22:57:12 +09:00
af005b6e5e Merge pull request #826 from juliogonzalez/centos-setup
For RPM distributions fuse-libs is enough
2018-10-08 22:50:29 +09:00
b19d2ae78f Improve template for issues 2018-10-07 01:20:10 +02:00
5634f9bdcd New installation instructions for Fedora >= 27 and CentOS7 2018-10-07 00:52:45 +02:00
c703fa15c0 Simplify hex conversion
Addresses GCC 8 warning:

common_auth.cpp: In function ‘std::__cxx11::string s3fs_sha256sum(int, off_t, ssize_t)’:
common_auth.cpp:84:12: warning: ‘char* strncat(char*, const char*, size_t)’ output may be truncated copying 2 bytes from a string of length 2 [-Wstringop-truncation]
    strncat(sha256, hexbuf, 2);
2018-10-01 19:08:27 -07:00
d9c106cfde Add support for storage class ONEZONE_IA. 2018-09-30 14:27:31 +02:00
203f78fdae For RPM distributions fuse-libs is enough 2018-09-23 19:35:17 +02:00
c5af62b023 Merge pull request #820 from gaul/big-writes
Enable big writes if capable
2018-09-17 17:24:06 +09:00
dcd70daf48 Merge pull request #819 from soulprovidr/master
#691: Made instructions for creating password file more obvious.
2018-09-17 17:01:53 +09:00
8263919b0e Merge pull request #812 from mapreri/typo
Fix typo s/mutliple/multiple/
2018-09-17 16:52:48 +09:00
97488e603f Merge pull request #804 from DreamFlasher/patch-2
add Backblaze B2
2018-09-17 16:43:55 +09:00
41c23adb0e [curl] Assume long encryption keys are base64 encoded
Amazon SSE-C https://tinyurl.com/ychug4cg writes:

> Use this header to provide the 256-bit, base64-encoded encryption key
> for Amazon S3 to use to encrypt or decrypt your data.

It seems likely that future keys would be as long, or longer, so
this change assumes that text longer than 32 characters are keys
that are base64 encoded.

Signed-off-by: Earl Chew <earl_chew@yahoo.com>
2018-09-16 21:23:22 +00:00
a85183d42c Enable big writes if capable
Fixes #813.
2018-09-10 22:21:51 -07:00
45b67b9604 #691: Made instructions for creating password file more obvious. 2018-09-09 23:11:12 -05:00
c376efdd28 Fix typo s/mutliple/multiple/
Signed-off-by: Mattia Rizzolo <mattia@mapreri.org>
2018-08-19 00:14:57 +02:00
4c5f510207 add Backblaze B2
this is relevant because Backblaze B2 is fairly popular and thus mentioning it helps s3fs
2018-07-17 13:49:31 +02:00
06032aa661 Merge pull request #795 from ggtakec/master
Updated ChangeLog and configure.ac for release 1.84
2018-07-08 18:22:54 +09:00
e8fb2aefb3 Updated ChangeLog and configure.ac for release 1.84 2018-07-08 09:06:52 +00:00
3cb6c5e161 Merge pull request #793 from ggtakec/master
Added list_object_max_keys option based on #783 PR
2018-07-08 13:08:47 +09:00
7e0c53dfe9 Added list_object_max_keys option based on #783 PR 2018-07-08 03:49:10 +00:00
c2ca7e43b6 Merge pull request #789 from juliogonzalez/doc-opensuse-suse
Instructions for SUSE and openSUSE prebuilt packages
2018-07-08 11:42:05 +09:00
ae47d5d349 Merge pull request #786 from ambiknai/log_enhancements
Log messages for 5xx and 4xx HTTP response code
2018-07-08 11:28:54 +09:00
35d3fce7a0 Review comment: Include the error code being returned 2018-07-06 05:14:32 -04:00
4177d8bd3b Review comment: Include the error code being returned 2018-07-06 03:03:57 -04:00
ad5349a488 Changes as per review comments 2018-07-05 05:02:04 -04:00
6b57a8c1fc Instructions for SUSE and openSUSE prebuilt packages 2018-07-05 10:23:26 +02:00
92a4034c5e Log messages for 5xx and 4xx HTTP response code 2018-07-04 03:50:45 -04:00
3e4002df0d Merge pull request #780 from wjt/initialize-libgcry
gnutls_auth: initialize libgcrypt
2018-06-24 12:48:08 +09:00
1b9ec7f4fc Merge pull request #774 from nkkashyap/master
Option for IAM authentication endpoint
2018-06-24 12:36:23 +09:00
4a7c4a9e9d Merge pull request #781 from ggtakec/master
Fixed an error by cppcheck on OSX
2018-06-24 12:22:35 +09:00
0d3fb0658a Fixed a error by cppcheck on OSX 2018-06-24 02:38:59 +00:00
73cf2ba95d gnutls_auth: initialize libgcrypt
Without this change, the following warning appears in the syslog/journal
during startup:

  Libgcrypt warning: missing initialization - please fix the application

From the [documentation][0]:

> The function `gcry_check_version` initializes some subsystems used by
> Libgcrypt and must be invoked before any other function in the
> library.

Fixes #524, which says:

> gnutls is initialized by gnutls_global_init() function and
> gcry_check_version() function for initializing libgcry is called from
> this gnutls_global_init().

I checked the gnutls source and it hasn't contained a call to
gcry_check_version() since the libgcrypt backend was removed in 2011
(commit 8116cdc8f131edd586dad3128ae35dd744cfc32f). In any case, the
gcry_check_version() documentation continues:

> It is important that these initialization steps are not done by a
> library but by the actual application.

so it would be incorrect for a library used by s3fs to initialize
libgcrypt.

[0]: https://www.gnupg.org/documentation/manuals/gcrypt/Initializing-the-library.html
2018-06-21 20:55:00 +01:00
5a481e6a01 Option for IBM IAM auth endpoint added return 2018-06-04 16:44:14 +05:30
d8e12839af Option for IBM IAM auth endpoint 2018-05-31 16:02:48 +05:30
3bf05dabea Merge pull request #769 from orozery/revert_to_async_read
Revert "enable FUSE read_sync by default"
2018-05-28 20:23:54 +09:00
d4e86a17d1 Revert "enable FUSE read_sync by default"
This reverts commit 86b0921ac4.

Conflicts:
	src/s3fs.cpp
2018-05-28 13:49:54 +03:00
6555e7ebb0 Merge pull request #768 from ggtakec/master
Fixed memory leak
2018-05-27 20:10:16 +09:00
ae9d8eb734 Fixed memory leak 2018-05-27 10:48:03 +00:00
e49d594db4 Merge pull request #766 from gaul/s3fs-python
Remove s3fs-python
2018-05-27 16:43:27 +09:00
66bb0898db Merge pull request #765 from gaul/debian
Add Debian installation instructions
2018-05-27 16:35:51 +09:00
b323312312 Remove s3fs-python
This no longer exists.
2018-05-23 16:06:41 -07:00
58e52bad4f Add Debian installation instructions 2018-05-23 16:03:02 -07:00
57b2a60172 Merge pull request #764 from orozery/remove_false_multihead_warnings
Remove false multihead warnings
2018-05-23 22:38:35 +09:00
212bbbbdf0 Merge pull request #763 from orozery/cleanup_share_after_handles
cleanup curl handles before curl share
2018-05-23 22:30:36 +09:00
a0e62b5588 Merge pull request #762 from gaul/s3proxy-1.6.0
Upgrade to S3Proxy 1.6.0
2018-05-23 22:23:33 +09:00
e9831dd772 Merge pull request #761 from gaul/ubuntu-16.04
Simplify installation for Ubuntu 16.04
2018-05-23 22:15:01 +09:00
da95afba8a Merge pull request #756 from orozery/optimize_defaults
Optimize defaults
2018-05-23 22:05:00 +09:00
0bd875eb9e remove false readdir_multi_head warnings 2018-05-22 17:10:50 +03:00
af63a42773 cleanup curl handles before curl share 2018-05-21 13:20:09 +03:00
ad9a374229 Simplify installation for Ubuntu 16.04
Also reorganize installation vs. compilation.
2018-05-16 17:40:13 -07:00
1b86e4d414 Upgrade to S3Proxy 1.6.0
Release notes:

https://github.com/gaul/s3proxy/releases/tag/s3proxy-1.6.0
https://github.com/gaul/s3proxy/releases/tag/s3proxy-1.5.5
https://github.com/gaul/s3proxy/releases/tag/s3proxy-1.5.4
2018-05-16 16:38:17 -07:00
86b0921ac4 enable FUSE read_sync by default 2018-05-06 16:10:36 +03:00
dbe98dcbd2 Merge pull request #755 from ggtakec/master
Added reset curl handle when returning to handle pool
2018-05-06 21:35:39 +09:00
4a72b60707 increase default stat cache size from 1000 to 100000 2018-05-06 15:31:07 +03:00
7a4696fc17 recommend openssl over gnutls for performance 2018-05-06 15:29:42 +03:00
e3de6ea458 Added reset curl handle when returning to handle pool 2018-05-06 12:11:53 +00:00
1db4739ed8 Merge pull request #754 from nkkashyap/master
Validate the URL format for http/https
2018-05-06 21:02:33 +09:00
25375a6b48 Validate the URL fixed inefficient usage of find 2018-05-04 11:24:32 +05:30
ca87df7d44 Validate the URL format for http/https 2018-05-03 22:08:28 +05:30
d052dc0b9d Merge pull request #753 from cfz/master
fix xpath selector in bucket listing
2018-05-02 12:04:12 +09:00
3f542e9cf5 Merge pull request #745 from orozery/handle_mkdir_exists
don't fail mkdir when directory exists
2018-05-02 11:37:18 +09:00
04493de767 fix xpath selector in bucket listing
the original implementation in get_base_exp() depends on the order of xml return from the server.
patriotically, when listing a directory with sub directory(s), the xml document response contains more than 2 <Prefix> nodes(some of them are in <CommonPrefixes> node).
the source code arbitrarily select the first one in the documents (nodes->nodeTab[0]->xmlChildrenNode).
some s3 compatible service return the list-bucket result in different result, leading the s3fs to a wrong behavior
2018-04-23 15:11:29 +08:00
4fdab46617 don't fail mkdir when directory exists 2018-04-08 11:13:47 +03:00
1a23b880d5 Merge pull request #739 from orozery/cleanup_failing_curl_handles
cleanup curl handle state on retries
2018-04-01 22:45:04 +09:00
b3c376afbe Merge pull request #733 from phxvyper/enhance/dupe-bucket-error
More useful error message for dupe entries in passwd file
2018-04-01 22:11:00 +09:00
adcf5754ae cleanup failing curl handles on retries 2018-03-29 13:56:08 +03:00
0863672e27 add a more helpful error message for when there are multiple entries for the same bucket in the passwd file 2018-03-13 14:37:34 -07:00
0f503ced25 Merge pull request #729 from dmgk/master
FreeBSD build fixes
2018-03-04 16:36:31 +09:00
987a166bf4 Merge pull request #726 from orozery/instance_name_logging
add an instance_name option for logging
2018-03-04 15:41:12 +09:00
57b6f0eeaf Merge pull request #724 from orozery/dont_fail_multirequest
don't fail multirequest on single thread error
2018-03-04 15:35:29 +09:00
f71a28f9b9 Merge pull request #714 from orozery/reduce_lock_contention
reduce lock contention on file open
2018-03-04 13:36:08 +09:00
45c7ea9194 Merge pull request #710 from orozery/disk_space_reservation
add disk space reservation
2018-03-04 13:27:25 +09:00
c9f4312588 FreeBSD build fixes 2018-03-02 15:58:52 -05:00
8b657eee41 add disk space reservation 2018-02-28 19:20:23 +02:00
b9c9de7f97 Merge pull request #712 from chrilith/master
Added Cygwin build options
2018-02-28 23:07:54 +09:00
e559f05326 Merge pull request #704 from vadimeremeev/patch-1
Update README.md with details about .passwd-s3fs
2018-02-28 22:22:01 +09:00
824124fedc Merge pull request #727 from ggtakec/master
Fixed Travis CI error about cppcheck - #713
2018-02-28 22:04:04 +09:00
be9d407fa0 Fixed cppcheck error on osx 2018-02-28 12:29:58 +00:00
c494e54320 Fixed cppcheck error on osx 2018-02-28 12:06:06 +00:00
b52b6f3fc5 add an instance_name option for logging 2018-02-28 09:51:35 +02:00
82c9733101 don't fail multirequest on single thread error 2018-02-26 12:06:08 +02:00
a45ff6cdaa Fixed cppcheck error and clean ^M code 2018-02-25 13:08:41 +00:00
960d45c853 Fixed cppcheck error on osx 2018-02-25 08:51:19 +00:00
246b767b64 Remove space in front of ~/.passwd-s3fs 2018-02-05 16:49:02 +07:00
0edf056e95 reduce lock contention on file open 2018-02-04 17:13:58 +02:00
88819af2d8 Added Cygwin build options 2018-02-02 15:58:10 +01:00
b048c981ad Update README.md with details about .passwd-s3fs 2017-12-22 16:20:02 +07:00
e1dafe76dd Merge pull request #701 from ggtakec/master
Updated ChangeLog and configure.ac for release 1.83
2017-12-17 16:53:49 +09:00
1a2e63ecff Updated ChangeLog and configure.ac for release 1.83 2017-12-17 07:37:19 +00:00
a60b32cb80 Merge pull request #699 from casidiablo/patch-1
Fix dbglevel usage
2017-12-17 15:55:24 +09:00
6b58220009 Merge pull request #697 from pwulff/master
Fixing race condition in FdEntity::GetStats
2017-12-17 15:46:48 +09:00
a841057679 Merge pull request #695 from orozery/fix_parallel_download_condition
fix condition for parallel download
2017-12-17 15:41:43 +09:00
ee6abea956 Race condition in FdManager::Rename because no mutex is used. 2017-12-15 15:27:51 +01:00
8b0acd75e0 Fix dbglevel usage 2017-12-14 14:37:18 -08:00
cea7d44717 Fixing race condition in FdEntity::GetStats 2017-12-13 10:49:00 +01:00
0da87e75fe fix condition for parallel download 2017-12-04 16:07:33 +02:00
566961c7a5 Merge pull request #692 from ggtakec/master
Updated template md files for issue and pr
2017-11-26 15:40:27 +09:00
ac65258d30 Updated template md files for issue and pr 2017-11-26 06:20:41 +00:00
35261e6dba Merge pull request #690 from ggtakec/master
Added option ecs description to man page
2017-11-23 21:40:11 +09:00
2818f23ba5 Added option ecs description to man page 2017-11-23 12:21:56 +00:00
88f071ea22 Merge pull request #669 from orozery/ibm_auth
add IBM IAM authentication support
2017-11-23 21:15:08 +09:00
bd4bc0e7f1 add support for IBM IAM authentication 2017-11-23 12:01:52 +02:00
890c1d53ff Merge pull request #688 from ggtakec/master
Improved use of temporary files - #678
2017-11-23 18:46:31 +09:00
026260e7a1 Improved use of temporary files 2017-11-23 09:18:11 +00:00
99fe93b7f1 Merge pull request #684 from gaul/signedness
Correct signedness warning
2017-11-23 17:33:46 +09:00
b764c53020 Merge pull request #686 from orozery/remove_jsoncpp
remove use of jsoncpp
2017-11-23 17:08:40 +09:00
11bd7128d2 remove use of jsoncpp 2017-11-22 13:36:27 +02:00
7cda32664b Correct signedness warning
Fixes regression from 0418e53b3c.
2017-11-19 11:14:37 -08:00
4c73a0ae56 Merge pull request #681 from ggtakec/master
Changed functions about reading passwd file
2017-11-19 21:06:45 +09:00
97fc845a6a Changed functions about reading passwd file. 2017-11-19 11:49:11 +00:00
7d9ac0163b Changed functions about reading passwd file. 2017-11-19 11:38:12 +00:00
d903e064e0 Merge pull request #677 from gaul/gitignore
Add s3proxy to .gitignore
2017-11-19 16:44:24 +09:00
e1928288fe Merge pull request #676 from gaul/sstream
Move str definition from header to implementation
2017-11-19 16:34:15 +09:00
6ab6412dd3 Merge pull request #679 from ggtakec/master
README.md Addition
2017-11-19 16:24:51 +09:00
30b7a69d3d README.md Addition 2017-11-19 07:03:39 +00:00
ccd0a446d8 Merge pull request #675 from gaul/define
Reduce use of preprocessor
2017-11-19 16:02:24 +09:00
0418e53b3c Reduce use of preprocessor
This provides type-safety and avoids token expansion side effects.
2017-11-18 22:40:06 -08:00
bad48ab59a Merge pull request #671 from psyvision/master
Add support for ECS metadata endpoint
2017-11-19 14:43:06 +09:00
bbad76bb71 Move str definition from header to implementation
Also clean up some char * to std::string conversions.
2017-11-18 11:34:34 -08:00
6c1bd98c14 Add s3proxy to .gitignore 2017-11-18 11:10:56 -08:00
b95e4acaeb Remove debug logging statements 2017-11-08 15:52:35 +00:00
c238701d09 Corrected ECS headers 2017-11-08 15:21:49 +00:00
60d2ac3c7a Adding x-amz-security-token header 2017-11-08 15:09:59 +00:00
967ef4d56b Corrected fat finger mistakes 2017-11-08 13:14:49 +00:00
ad57bdda6c Corrected keycount check 2017-11-08 13:06:22 +00:00
a0b69d1d3d Corrected keyval[].c_str() 2017-11-08 13:01:52 +00:00
5df94d7e33 Add debug messages 2017-11-08 09:50:39 +00:00
1cbe9fb7a3 Gotta pass that cppcheckgit add . 2017-11-07 21:41:51 +00:00
395f736753 Lower jsoncpp requirement 2017-11-07 21:38:01 +00:00
065516c5f3 Add jsoncpp to tavis config 2017-11-07 21:29:07 +00:00
8660abaea2 Use jsoncpp to parse AWS JSON 2017-11-07 21:20:02 +00:00
366f0705a0 ECS credentials bug fixes 2017-11-06 21:45:58 +00:00
ccea87ca68 Added check for is_ecs during get_access_keys
We need to presume that if `is_ecs` we are deferring access key loading
2017-11-06 11:02:27 +00:00
5d54883e2f Remove commented out code 2017-11-05 19:25:34 +00:00
662f65c3c8 Add support for ECS metadata endpoint 2017-11-05 19:24:02 +00:00
259f028490 Merge pull request #670 from ggtakec/master
Fixed a bug in S3fsCurl::LocateBundle
2017-11-05 20:37:12 +09:00
5db550a298 Fixed a bug in S3fsCurl::LocateBundle 2017-11-05 11:26:05 +00:00
e3c77d2906 Merge pull request #664 from orozery/auth_refactor
auth headers insertion refactoring
2017-11-05 15:14:40 +09:00
ba00e79253 Merge pull request #668 from ggtakec/master
Changed .travis.yml for fixing not found gpg2 on osx
2017-11-05 14:47:41 +09:00
c1791f920e Changed .travis.yml for fixing not found gpg2 on osx 2017-11-05 05:32:41 +00:00
df3803c7b7 Merge pull request #663 from gaul/orgmeta-lock
Lock FdEntity when mutating orgmeta
2017-11-05 13:53:14 +09:00
384b4cbafa auth headers insertion refactoring 2017-10-30 11:52:58 +02:00
40501a7a73 Lock FdEntity when mutating orgmeta
References #654.
2017-10-23 22:41:42 -07:00
ab89b4cd4a Merge pull request #659 from ggtakec/master
Do not fail updating directory when removing old-style object(ref #658)
2017-10-15 21:56:35 +09:00
48e0d55c8e Merge pull request #660 from s3fs-fuse/patch
Refixed s3fs_init message(ref #652)
2017-10-15 16:01:45 +09:00
1eba27a50a Refixed s3fs_init message(ref #652) 2017-10-15 06:45:19 +00:00
41206fa0e2 Do not fail updating directory when removing old-style object(ref #658) 2017-10-15 05:03:44 +00:00
21cf1d64e5 Merge pull request #652 from jurafxp/fix-error
Fix s3fs_init message
2017-10-15 12:36:12 +09:00
ae91b6f673 Fix s3fs_init message 2017-10-01 00:08:00 +02:00
f4515b5cfa Merge pull request #646 from andrewgaul/s3proxy-pid
Simplify S3Proxy PID handling
2017-09-20 05:17:00 +09:00
6c57cde7f9 Merge pull request #645 from andrewgaul/s3proxy-ssl
Configure S3Proxy for SSL
2017-09-19 21:39:32 +09:00
5014c1827b Simplify S3Proxy PID handling
Also remove log prefixing since newer S3Proxy versions do this
already.  Finally remove unnecessary wait.
2017-09-17 20:19:56 -07:00
f531e6aff2 Configure S3Proxy for SSL
This also demonstrates that SSL certificate checking occurs and the
tests must disable it for S3Proxy's self-signed certificate.
References #640.
2017-09-17 16:16:18 -07:00
c5c110137b Merge pull request #644 from ggtakec/master
Fixed with unnecessary equal in POST uploads url argment - #643
2017-09-17 20:08:53 +09:00
5957d9ead0 Fixed with unnecessary equal in POST uploads url argment - #643 2017-09-17 10:52:28 +00:00
5675df2a44 Merge pull request #642 from ggtakec/master
Fixed potential atomic violation in S3fsCurl::AddUserAgent - #633
2017-09-17 18:40:34 +09:00
00bc9142c4 Fixed potential atomic violation in S3fsCurl::AddUserAgent - #633 2017-09-17 09:16:05 +00:00
5653ab39fc Merge pull request #639 from andrewgaul/homebrew
Update Homebrew instructions
2017-09-17 15:43:03 +09:00
473dd7c940 Merge pull request #637 from andrewgaul/non-aws-s3
Add blurb about non-Amazon S3 implementations
2017-09-17 15:37:13 +09:00
ee824d52ba Merge pull request #638 from andrewgaul/readme-fixes
Minor fixes to README
2017-09-17 15:31:09 +09:00
7c5fba9890 Merge pull request #636 from swt2c/macos_upload_failures
Fix intermittent upload failures on macOS
2017-09-17 15:23:48 +09:00
f214cb03b2 Update Homebrew instructions
These moved to homebrew-core:

https://github.com/Homebrew/homebrew-core/pull/11283
2017-09-12 18:58:19 -07:00
416c51799b Minor fixes to README 2017-09-12 18:44:27 -07:00
cf6f665f03 Add blurb about non-Amazon S3 implementations
References #629.
2017-09-12 18:09:56 -07:00
20da0e4dd3 Fix intermittent upload failures on macOS
There were multiple problems with the FdManager::GetFreeDiskSpace() function
on macOS:
1) When calling statvfs(), f_frsize should be used instead of f_bsize when
converting available blocks to bytes.  This was causing the free space
calculation to be incorrect.
2) On macOS, fsblkcnt_t is a 32-bit integer.  Thus, when calculating available
disk space, there were frequently overflows.  This caused s3fs to incorrectly
determine that the cache location was out of space in the middle of a transfer
which caused uploads to fail.  Changing this to a uint64_t resolves the
problem.
2017-09-08 15:23:10 -04:00
fa8c417526 Merge pull request #631 from s3fs-fuse/macosx
Merged macosx branch into master branch #601
2017-08-12 00:13:10 +09:00
2c65aec6c8 Merge pull request #630 from ggtakec/macosx
Added travis test on osx for #601
2017-08-11 23:46:51 +09:00
96d8e6d823 Merge remote-tracking branch 'upstream/macosx' into macosx 2017-08-11 14:20:12 +00:00
62b8084300 Added travis test on osx for #601 2017-08-11 14:09:43 +00:00
907aff5de4 Merge pull request #627 from swordsreversed/master
Update README.md
2017-08-02 22:14:08 +09:00
bc09129ec5 Update README.md 2017-08-01 10:20:46 +10:00
cd94f638e2 Update README.md
Add fuse as a dependency!
2017-07-31 21:23:08 +10:00
b1fe419870 Merge pull request #621 from andrewgaul/s3proxy
Upgrade to S3Proxy 1.5.3
2017-07-10 21:13:26 +09:00
98b724391f Upgrade to S3Proxy 1.5.3
Release notes:

https://github.com/andrewgaul/s3proxy/releases/tag/s3proxy-1.5.3
2017-07-09 22:41:39 -07:00
620f6ec616 Merge pull request #611 from ggtakec/master
Fixed clock_gettime build failure on macOS 10.12 Sierra - #600
2017-05-28 19:15:45 +09:00
0c6a3882a2 Fixed clock_gettime build failure on macOS 10.12 Sierra - #600 2017-05-28 10:04:25 +00:00
a08880ae15 Merge pull request #608 from tlevi/chown_nocopy
Fix chown_nocopy losing existing uid/gid if unspecified
2017-05-28 18:36:08 +09:00
f48826dfe9 Merge pull request #609 from tlevi/getgrgid_r
Group permission checks sometimes fail with large number of groups
2017-05-27 11:02:18 +09:00
9c3551478e Merge pull request #606 from andrewgaul/homebrew
Add Homebrew instructions
2017-05-27 11:01:01 +09:00
cc94e1da26 Fix chown_nocopy losing existing uid/gid if unspecified 2017-05-25 16:53:08 +09:30
2b7ea5813c Expand buffer for group information if too small and retry 2017-05-23 10:42:43 +09:30
185192be67 Add Homebrew instructions 2017-05-22 10:12:22 -07:00
ae4caa96a0 Merge pull request #598 from ggtakec/master
Updated ChangeLog and configure.ac for release 1.82
2017-05-14 01:25:34 +09:00
af13ae82c1 Updated ChangeLog and configure.ac for release 1.82 2017-05-13 16:12:46 +00:00
13503c063b Merge pull request #597 from ggtakec/master
Not fallback to HTTP - #596
2017-05-14 01:01:36 +09:00
337da59368 Not fallback to HTTP - #596 2017-05-13 15:47:39 +00:00
b0681246b9 Merge pull request #595 from ggtakec/master
Updated ChangeLog and configure.ac for release 1.81
2017-05-13 20:12:47 +09:00
52853f6b47 Updated ChangeLog and configure.ac for release 1.81 2017-05-13 11:02:54 +00:00
f6eb841a24 Updated ChangeLog and configure.ac for release 1.81 2017-05-13 10:54:54 +00:00
caea087aec Merge pull request #594 from ggtakec/master
Check bucket at public bucket and add nocopyapi option automatically
2017-05-13 17:01:21 +09:00
d2ae14d8b7 Check bucket at public bucket and add nocopyapi option automatically 2017-05-13 07:48:50 +00:00
7115835834 Check bucket at public bucket and add nocopyapi option automatically 2017-05-13 07:35:55 +00:00
551c6acf67 Merge pull request #593 from ggtakec/master
Backward compatible for changing default transport to HTTPS
2017-05-13 16:09:22 +09:00
24df69f688 Backward compatible for changing default transport to HTTPS 2017-05-13 06:47:51 +00:00
23a10dd644 Merge pull request #590 from ggtakec/master
Updated man page for default_acl option - #567
2017-05-09 23:29:04 +09:00
034042f511 Updated man page for default_acl option - #567 2017-05-09 14:18:19 +00:00
465c15ef40 Merge pull request #588 from andrewgaul/https
Default transport to HTTPS
2017-05-09 23:04:57 +09:00
a22675bafd Merge pull request #567 from andrewgaul/default-acl
Do not send ACL unless overridden
2017-05-09 23:03:27 +09:00
0e0ae38f6d Default transport to HTTPS
This protects private data when used over the public Internet.  Users
can opt-in to unencrypted HTTP if they need additional performance on
a local network.  Fixes #282.
2017-05-07 10:59:54 -07:00
7b30d5d15b Do not send canned ACL header when empty string
Some providers such as StorageGRID do not support canned ACLs.
Setting to empty allows callers to omit the header.  References #125.
2017-05-07 10:52:31 -07:00
4a5c9bef89 Merge pull request #587 from ggtakec/master
Changed copyright year format for debian pkg
2017-05-07 20:33:38 +09:00
9d10a5aa70 Changed copyright year format for debian pkg 2017-05-07 11:24:17 +00:00
107757f11d Merge pull request #585 from ggtakec/master
Fixed failure to upload/copy with SSE_C and SSE_KMS
2017-05-07 18:56:17 +09:00
a12e0d5ec4 Fixed failure to upload/copy with SSE_C and SSE_KMS 2017-05-07 09:29:08 +00:00
42cdcbc2dc Merge pull request #583 from ggtakec/master
Updated limit object size in s3fs man page
2017-05-06 13:51:01 +09:00
eef549dac7 Updated limit object size in s3fs man page 2017-05-06 04:34:07 +00:00
c8ee132813 Merge pull request #582 from ggtakec/master
Check errors returned in 200 OK responses for put header request
2017-05-06 11:28:51 +09:00
d07c3f38b7 Check errors returned in 200 OK responses for put header request 2017-05-06 02:15:53 +00:00
73da168b93 Merge pull request #580 from ggtakec/master
Enhanced bucket/path parameter check
2017-05-06 05:13:05 +09:00
1fe0334c08 Enhanced bucket/path parameter check 2017-05-05 19:55:24 +00:00
7d09914f1f Merge pull request #579 from ggtakec/master
Added notsup_compat_dir option
2017-05-06 02:38:36 +09:00
3ac39d61f8 Added notsup_compat_dir option 2017-05-05 17:28:29 +00:00
c5677b4726 Merge pull request #578 from ggtakec/master
Refactored the get_object_attribute function
2017-05-05 19:24:01 +09:00
67685c3d49 Merge pull request #1 from ggtakec/test
Refactored the get_object_attribute function
2017-05-05 19:09:45 +09:00
864e20e1f2 Refactored the get_object_attribute function 2017-05-05 10:02:21 +00:00
51b3183cba Refactored the check_object_access function 2017-05-05 09:51:30 +00:00
f02b1bc352 Merge pull request #576 from ggtakec/master
Added option for complementing lack of stat mode
2017-05-04 13:12:47 +09:00
758b92e823 Added option for complementing lack of stat mode 2017-05-04 03:41:24 +00:00
df0ff3a2fd Merge pull request #556 from orozery/fix_nocache_multipart_upload
fix multipart upload handling without cache
2017-04-16 19:22:15 +09:00
edcf4c6218 Merge pull request #555 from orozery/dont_sign_empty_headers
don't sign empty headers (as they are discarded by libcurl)
2017-04-16 19:16:47 +09:00
28efff5986 Merge pull request #554 from orozery/cache_cleanup
cleanup cache directory when running out of disk space
2017-04-16 19:13:11 +09:00
efba9bcbc1 Merge pull request #553 from orozery/custom_cipher_suite
add TLS cipher suites customization
2017-04-16 19:09:27 +09:00
6bd179c92b Merge pull request #552 from orozery/foreground_threads
switch S3fsMultiCurl to use foreground threads
2017-04-16 19:05:16 +09:00
96764b7410 switch S3fsMultiCurl to use foreground threads 2017-04-09 16:56:49 +03:00
ff3eb1971f Merge branch 'master' into fix_nocache_multipart_upload 2017-04-09 22:13:33 +09:00
94ddcb8d4f Merge pull request #560 from ggtakec/master
Fixed about multipart uploading at no free space related to #509
2017-04-09 14:06:23 +09:00
b4c90d6957 Fixed a bug about multipart uploading at no disk free space related to #509 2017-04-09 04:37:20 +00:00
75b59a7c16 switch S3fsMultiCurl to use foreground threads 2017-04-04 15:32:53 +03:00
3bcca75a88 don't sign empty headers (as they are discarded by libcurl) 2017-04-04 15:24:20 +03:00
79ea1a1561 Merge pull request #558 from ggtakec/master
Fixed a bug in logic about truncating stat cache
2017-04-02 21:02:15 +09:00
f0f61b3b55 Fixed a bug in logic about truncating stat cache 2017-04-02 11:51:58 +00:00
b955391621 Merge pull request #557 from ggtakec/master
Added check_cache_dir_exist option(refixed #347) - #538
2017-04-02 17:32:08 +09:00
8de992d42d Added check_cache_dir_exist option(refixed #347) - #538 2017-04-02 08:17:12 +00:00
fef3fbc225 Added check_cache_dir_exist option(refixed #347) - #538 2017-04-02 08:10:16 +00:00
acb61880b9 Merge pull request #551 from ggtakec/master
Updated stat_cache_expire option description - #545
2017-04-02 16:32:47 +09:00
8ee95ff7ab fix multipart upload handling without cache 2017-04-02 10:27:43 +03:00
95578cad43 cleanup cache directory when running out of disk space 2017-04-02 10:22:12 +03:00
465bbd3729 Updated stat_cache_expire option description - #545 2017-04-02 07:19:16 +00:00
0fa895594e Merge pull request #550 from Vascom/patch-1
Add umount instruction for unplivileged user.
2017-04-02 16:05:40 +09:00
15573cd21e Add umount instruction for unplivileged user.
Ordinary user has no permissions to use umount command, so it is good add fuse unmount instruction in man file.
2017-03-29 11:43:05 +03:00
43df94719b Merge pull request #546 from ggtakec/master
Fixed double initialization of SSL library at foreground
2017-03-20 02:22:19 +09:00
980ba398bc Fixed double initialization of SSL library - #524 2017-03-19 17:11:18 +00:00
0d59ac51c1 Merge pull request #545 from ggtakec/master
Changed base cached time of stat_cache_expire option - #523
2017-03-20 00:40:26 +09:00
523043a2aa Changed base cached time of stat_cache_expire option - #523 2017-03-19 15:19:04 +00:00
277da2c64a Merge pull request #540 from andrewgaul/cppcheck
Address cppcheck 1.77 warnings
2017-03-19 15:27:34 +09:00
03217baa99 Address cppcheck 1.77 warnings 2017-03-06 12:41:08 -08:00
6affefff5b Merge pull request #509 from andrewgaul/mpu
Use server-provided ETag during complete upload
2017-03-06 21:54:51 +09:00
2506fe73fa Merge pull request #539 from andrewgaul/s3proxy
Upgrade to S3Proxy 1.5.2
2017-03-06 21:48:18 +09:00
25a03c370a Upgrade to S3Proxy 1.5.2
Release notes:

https://github.com/andrewgaul/s3proxy/releases/tag/s3proxy-1.5.2
2017-03-02 10:55:24 -08:00
d40da2c68b Merge pull request #520 from ggtakec/master
Added links for eventual consistency in README.md - #515
2017-01-15 17:38:27 +09:00
7d6312ac78 Added links for eventual consistency in README.md - #515 2017-01-15 08:23:55 +00:00
e26c69a327 Merge pull request #517 from hudsantos/master
Update s3fs.1 - removed duplicated word
2017-01-09 10:48:29 +09:00
ff196e4257 Update s3fs.1 2016-12-16 19:16:17 -02:00
19f0d498aa Merge pull request #513 from ggtakec/master
Added issue and PR templates.
2016-12-04 21:33:55 +09:00
97a806447e Added issue and PR templates. 2016-12-04 12:25:11 +00:00
a00af2385b Merge pull request #512 from ggtakec/master
Changed clock_gettime func to s3fs_clock_gettime for homebrew - #468
2016-12-04 19:42:29 +09:00
6fc972972f Changed clock_gettime func to s3fs_clock_gettime for homebrew - #468 2016-12-04 10:31:41 +00:00
989d403b1f Merge remote-tracking branch 'upstream/master' 2016-12-04 08:40:58 +00:00
7b307601b5 Merge pull request #511 from s3fs-fuse/issue#435
Fixed a bug about uploading NULL to some part of the file contents
2016-12-04 17:20:50 +09:00
d731ab3a8e force java to use openjdk7 2016-12-04 08:14:02 +00:00
174d934d52 Initializing java package by update-alternatives 2016-12-04 08:04:33 +00:00
b428f68acf Patched openjdk java path on travis at 12/4/2016 2016-12-04 07:45:28 +00:00
5350e03147 Test configure for what version of java openjdk 2016-12-04 07:23:23 +00:00
28c7888a50 Sepalated install openjdk-7-jdk for checking why travis could not install it. 2016-12-04 07:01:28 +00:00
915a1321c7 Use server-provided ETag during complete upload
This avoids calculating the MD5 locally and enables use with object
stores which do not use MD5 as ETag.
2016-11-23 18:48:57 -08:00
8a11d7bc2f Merge pull request #505 from andrewgaul/spelling
Correct typos
2016-11-20 09:10:27 +09:00
7aae4782d9 Merge pull request #504 from andrewgaul/test
Use describe helper function
2016-11-20 09:10:16 +09:00
aba9e29471 Merge pull request #503 from andrewgaul/mtime-test
Add missing call to mtime test
2016-11-20 09:10:08 +09:00
d375bca0d0 Correct typos 2016-11-19 15:57:41 -08:00
cd0c8599cc Use describe helper function 2016-11-19 15:36:02 -08:00
20878a1618 Add missing call to mtime test 2016-11-19 15:10:41 -08:00
edd0a11fb5 Merge pull request #494 from mapreri/typo
Fix typo s/destroied/destroyed/
2016-11-20 05:53:23 +09:00
5e4bafeab7 Merge pull request #498 from andrewgaul/s3proxy
Upgrade to S3Proxy 1.5.1
2016-11-20 05:44:07 +09:00
67a836223a Merge pull request #495 from driskell/fix_sse_copy
Fix invalid V4 signature on multipart copy requests
2016-11-20 05:43:10 +09:00
7e2d6a3eed Merge remote-tracking branch 'upstream/issue#435' 2016-11-19 20:36:02 +00:00
1ee5a468f4 Merge pull request #502 from ggtakec/issue#435
Fixed issue#435 branch codes for remaining bugs(2)
2016-11-20 05:28:10 +09:00
81e209bdd1 Fixed issue#435 codes 2016-11-19 20:09:35 +00:00
90eda81624 Merge remote-tracking branch 'upstream/issue#435' 2016-11-19 19:52:27 +00:00
cafe6015e3 Upgrade to S3Proxy 1.5.1
Enabled previously broken tests and test with default v4 signer.
Release notes:

https://github.com/andrewgaul/s3proxy/releases/tag/s3proxy-1.5.0
https://github.com/andrewgaul/s3proxy/releases/tag/s3proxy-1.5.1
2016-11-15 23:09:48 -08:00
2492dc60ce Fix invalid V4 signature on multipart copy requests 2016-11-15 23:09:23 -08:00
6f688770fd Fix invalid V4 signature on multipart copy requests 2016-11-13 13:22:00 +00:00
8c0b1d9c5b Fix typo s/destroied/destroyed/ 2016-11-11 23:27:17 +00:00
efde0ec9de Merge pull request #489 from ggtakec/master
Changed headers_t map using nocase compare function - #488
2016-10-23 23:23:31 +09:00
632495374b Chnaged headers_t map using nocase compare function - #488 2016-10-23 14:14:19 +00:00
15b797f3ee Merge pull request #488 from ggtakec/master
Fixed searching Content-Length without case sensitive - #480
2016-10-23 22:42:52 +09:00
a7a64d954a Fixed searching Content-Length without case sensitive - #480 2016-10-23 13:27:01 +00:00
cca217f613 Merge pull request #487 from driskell/debugging
Split header debugging onto multiple lines for easier reading
2016-10-23 21:51:38 +09:00
1a9cf6f66d Fixed searching Content-Length without case sensitive - #480 2016-10-23 12:40:51 +00:00
02d7296210 Split header debugging onto multiple lines for easier reading 2016-10-22 15:11:18 +01:00
a688df813e Fixed a bug at read symlink 2016-10-11 13:32:08 +00:00
164424bc89 Merge branch 'master' into issue#435 2016-10-11 12:13:03 +00:00
f38aaa3d0e Merge pull request #483 from ggtakec/master
Trim symbolic link original path in file.
2016-10-11 19:31:34 +09:00
7fabd18b1f Trim symbolic link original path in file. 2016-10-11 10:22:30 +00:00
5db369d67e Trim symbolic link original path in file. 2016-10-11 10:17:46 +00:00
dba32fdf78 Trim symbolic link original path in file. 2016-10-11 10:06:21 +00:00
716baada22 Testing patch codes for issue#435 2016-10-10 12:16:09 +00:00
1a93897e85 Merge pull request #477 from ggtakec/master
OS-specific correspondence of the extended attribute header
2016-10-02 16:34:55 +09:00
9fd1368611 OS-specific correspondence of the extended attribute header 2016-10-02 07:23:19 +00:00
9f174d7614 Merge pull request #471 from ggtakec/master
Added use_xattr option for #467 and #460
2016-09-19 14:00:20 +09:00
65d52506c4 Added use_xattr option for #467 and #460 2016-09-19 04:28:01 +00:00
a56fe0ea28 Merge pull request #466 from ggtakec/master
Fixed a bug about could not copy file mode from org file
2016-09-11 23:11:22 +09:00
ec110bb0f3 Added small logic in test script for test_chown 2016-09-11 13:41:50 +00:00
232befb52a Added small logic in test script for test_chown 2016-09-11 13:37:53 +00:00
f363c21ff5 Added comments in failure message for test_chown 2016-09-11 13:28:40 +00:00
1a96f40a10 Fixed a bug about could not copy file mode from org file 2016-09-11 13:09:23 +00:00
6be3236b28 Merge pull request #451 from kasbah/patch-1
Correct path in README
2016-07-24 17:32:35 +09:00
ccefd835d0 Merge pull request #454 from ggtakec/master
Changed for accepting mount options compatible with mtab - #449
2016-07-24 17:31:45 +09:00
1ddc14d59d Changed for accepting mount options compatible with mtab - #449 2016-07-24 08:17:58 +00:00
87f617374a Merge pull request #449 from treestem/mountopt
Accept mount options compatible with mtab
2016-07-24 16:48:33 +09:00
b76fc350b0 Merge pull request #447 from dsulli99/master
added fuse package for mounting via /etc/fstab, fixes #417
2016-07-18 22:25:30 +09:00
4deb6fdd84 added fuse package for mounting via /etc/fstab, fixes #417 2016-07-15 06:12:47 -05:00
2d5be2157a Correct path in README 2016-07-14 16:55:03 +01:00
a19206cf0f Accept mount arguments compatible with mtab
Using "mount -a" fails for already-mounted s3fs directories,
because s3fs mount arguments don't match the form in /etc/mtab.
Calling "mount -a" should quietly succeed when a directory is
already mounted.

To fix this, accept mount commands of the form:

s3fs s3fs /srv/object-store -o bucket=mybucket

or in /etc/fstab form:

s3fs  /srv/object-store  fuse.s3fs  bucket=mybucket 0 0

This matches the form in /etc/mtab and allows "mount -a" to
work properly.
2016-07-13 17:23:33 -04:00
0f9428ad5a Add mirror file logic for removing cache file 2016-07-13 17:23:32 -04:00
d748b333ee Merge pull request #444 from ggtakec/master
Add mirror file logic for removing cache file
2016-07-03 13:07:59 +09:00
e8a8019a71 Add mirror file logic for removing cache file 2016-07-03 03:37:08 +00:00
e8680b485d Merge pull request #443 from tlevi/master
Fix for leaks during stat cache entry expiry / truncation (#340)
2016-07-03 12:24:41 +09:00
ab4b92074c Fix cppcheck complaint 2016-06-30 11:51:25 +09:30
d57c12d3c3 Possible fix for leaks during entry expiry / truncation (#340) 2016-06-28 15:01:14 +09:30
676b2090fb Merge pull request #440 from ggtakec/master
Handled all curl error without exiting process - #437
2016-06-27 20:04:29 +09:00
6005929a96 Handled all curl error without exiting process - #437 2016-06-27 10:38:49 +00:00
49ffaa1d94 Merge pull request #432 from andrewgaul/create-bucket-location
Include location constraint when creating bucket
2016-06-26 09:39:47 +09:00
9fb3fd1a4d Merge pull request #433 from andrewgaul/typo
Correct search and replace typo
2016-06-14 21:45:01 +09:00
28b2b5cac3 Merge pull request #431 from mapreri/typo
fix typo s/controll/control/
2016-06-14 21:43:37 +09:00
320b8e1171 Include location constraint when creating bucket
This allows creating buckets in non-default regions.  Also improve
do_create_bucket error handling.
2016-06-13 10:35:37 -07:00
95cb5d201f Correct search and replace typo 2016-06-13 10:25:33 -07:00
880708ab5f fix typo s/controll/control/ 2016-06-12 15:02:40 +00:00
36917f7780 Merge pull request #426 from s3fs-fuse/ggtakec-patch-directly
Updated to correct ChangeLog
2016-05-29 12:40:28 +09:00
fe44f81ef2 Updated to correct ChangeLog
Because there was an extra line break
2016-05-29 12:37:16 +09:00
a81a2091c3 Merge pull request #425 from ggtakec/master
Updated ChangeLog and configure.ac for release 1.80
2016-05-29 12:29:06 +09:00
88d6c20cde Updated ChangeLog and configure.ac for release 1.80 2016-05-29 03:19:02 +00:00
4ff41f2ebf Merge pull request #424 from ggtakec/master
Added travis CI badge in README.md
2016-05-29 12:02:19 +09:00
a7d2148c60 Added travis CI badge in README.md
Added travis CI badge in README.md.
2016-05-29 11:40:58 +09:00
980c0f81dd Merge pull request #422 from nturner/fix/iam-role-auto
Fixes for iam_role=auto
2016-05-29 09:22:58 +09:00
775e493b0a Merge pull request #420 from nturner/master
Skip early credential checks when iam_role=auto
2016-05-29 09:11:24 +09:00
584ea488bf Use role name instead of profile name when iam_role=auto
When using an instance with an IAM Role, transient credentials can be
found in http://169.254.169.254/latest/meta-data/ at
iam/security-credentials/role-name and s3fs tries to do this. However,
it is using the profile-name where role-name is needed. In many cases
the role and profile name are the same, but they are not always.

The simplest way to find the role name appears to be to GET
http://169.254.169.254/latest/meta-data/iam/security-credentials/
itself, which returns a listing of the role names for which temporary
credentials exist. (I think there will probably only be one, but we
probably want to split on newlines and take the first one here in case
that assumption is not valid). This is the approach the AWS SDK appears
to use (based on WireShark analysis).

Bug: https://github.com/s3fs-fuse/s3fs-fuse/issues/421
Signed-off-by: Nathaniel W. Turner <nate@houseofnate.net>
2016-05-24 13:34:19 -04:00
594c9ca7d2 Skip early credential checks when iam_role=auto
If user specifies iam_role=auto (or just iam_role), credentials will not
be loaded during early phase, so skip credential checks there.

Signed-off-by: Nathaniel W. Turner <nate@houseofnate.net>
2016-05-20 12:49:02 -04:00
c2b7a7e453 Merge pull request #415 from ggtakec/master
Fixed a bug about stat_cache_expire - #382
2016-05-14 18:14:56 +09:00
34b604cdfe Fixed a bug about stat_cache_expire - #382 2016-05-14 09:03:52 +00:00
d16d616f34 Merge pull request #411 from ggtakec/master
loading IAM role name automatically(iam_role option) - #387
2016-05-06 13:57:32 +09:00
50f1ad51c8 loading IAM role name automatically(iam_role option) - #387 2016-05-06 04:37:32 +00:00
fe253c3d22 Merge pull request #410 from ggtakec/master
Allow duplicate key in ahbe_conf - #386
2016-05-06 10:21:50 +09:00
6cc30eea44 Allow duplicate key in ahbe_conf - #386 2016-05-06 01:08:39 +00:00
6be264a17f Merge pull request #409 from ggtakec/master
Fixed 'load_sse_c' option not working - #388
2016-05-06 09:47:39 +09:00
1ddbd4d6bb Fixed 'load_sse_c' option not working - #388 2016-05-06 00:36:54 +00:00
845fdb43f2 Merge pull request #404 from rockuw/keep-alive
Add curl handler pool to reuse connections
2016-04-26 23:40:45 +09:00
72f6c4d2dc Merge pull request #403 from rockuw/master
Fix a bug of truncating empty file
2016-04-26 23:35:22 +09:00
cf23dc78ab Use 'return' instead of 'exit' in test 2016-04-22 16:24:26 +08:00
b78adb4bb0 Add curl handler pool to reuse connections 2016-04-22 14:57:31 +08:00
115bd51f3f Fix a bug of truncating empty file 2016-04-22 14:49:37 +08:00
b979d40778 Merge pull request #397 from ggtakec/master
Supported User-Agent header - #383
2016-04-17 17:01:59 +09:00
10589a9497 Supported User-Agent header - #383 2016-04-17 07:44:03 +00:00
2f5973c02b Merge pull request #395 from ggtakec/master
Fixed writing sparsed file - #375,#379,#394
2016-04-13 03:34:44 +09:00
090c37a1c1 Fixed writing sparsed file - #375,#379,#394 2016-04-12 18:24:36 +00:00
d048f380c1 Merge pull request #394 from s3fs-fuse/revert-379-master
Revert "Fixed a bug about writing sparsed file - #375"
2016-04-13 01:30:34 +09:00
fff40bbff3 Revert "Fixed a bug about writing sparsed file - #375" 2016-04-13 01:24:24 +09:00
daef00e38b Merge pull request #391 from dreh23/patch-1
Update s3fs.1
2016-04-10 15:39:21 +09:00
4ca1b90d00 Merge pull request #385 from mapreri/typo
fix typo in curl.cpp: s/returing/returning/

@mapreri thanks!
2016-04-10 14:02:57 +09:00
c5691b6c7c Merge pull request #376 from RobbKistler/seek-test
Test for writing after an lseek past end of file
2016-04-10 13:00:10 +09:00
fb2ee7cc02 Update s3fs.1 2016-04-09 00:31:01 +02:00
136ec654c2 fix typo in curl.cpp: s/returing/returning/ 2016-04-02 15:19:06 +00:00
4e583583cd Test for writing after an lseek past end of file
This is a test to demonstrate Issue #375
2016-03-23 16:03:38 -07:00
91861e7fcd Merge pull request #379 from ggtakec/master
Fixed a bug about writing sparsed file - #375
2016-03-22 15:06:31 +09:00
ded4faf2e4 Fixed a bug about writing sparsed file - #375 2016-03-22 05:44:14 +00:00
cf56b35766 Merge pull request #372 from ggtakec/master
Fixed a bug about etag comparison in stats cache, etc.
2016-03-13 18:59:38 +09:00
98d55582eb Chnaged about constructor(destructor) in cache.h 2016-03-13 09:47:37 +00:00
84bdd51021 Fixed a bug about etag comparison in stats cache. 2016-03-13 09:29:06 +00:00
fbd8959d69 Merge pull request #371 from ggtakec/master
Always set stats cache for opened file
2016-03-13 15:15:30 +09:00
67efc11d94 Always set stats cache for opened file 2016-03-13 05:43:28 +00:00
d6e6eebb95 Merge pull request #364 from ggtakec/master
Checked content-type by no case-sensitivity - #363
2016-02-13 15:08:23 +09:00
4c65c09f4d Checked content-type by no case-sensitivity - #363 2016-02-13 05:58:59 +00:00
b281328ff4 Merge pull request #359 from yurykats/issue358
Issue 358: Remove optional parameter from Content-Type header
2016-02-11 12:19:25 +09:00
e9d2b38726 Merge pull request #360 from RobbKistler/configure
Fix clock_gettime autotools detection on Linux
2016-02-10 00:41:14 +09:00
f4aac111a4 Fix clock_gettime autotools detection on Linux 2016-02-08 13:45:34 -08:00
230991782b Update s3fs_util.cpp 2016-02-08 16:39:56 -05:00
ac99df5c09 Merge pull request #357 from ggtakec/master
Fixed codes about clock_gettime for osx(3)
2016-02-07 17:30:23 +09:00
f81e6103cb Fixed codes about clock_gettime for osx(3) 2016-02-07 08:27:02 +00:00
cd04cb0875 Merge pull request #356 from ggtakec/master
Fixed codes about clock_gettime for osx(2)
2016-02-07 17:14:32 +09:00
0755c6f60c Fixed codes about clock_gettime for osx(2) 2016-02-07 08:10:23 +00:00
1c9d7a9ea9 Merge pull request #355 from ggtakec/master
Fixed codes about clock_gettime for osx
2016-02-07 16:44:20 +09:00
e01ded9e27 Fixed codes about clock_gettime for osx 2016-02-07 07:40:55 +00:00
bf056b213a Merge pull request #354 from ggtakec/master
Supported regex type for additional header format - #343
2016-02-07 15:16:51 +09:00
1af7aaeccb Fixed addhead.cpp for cppcheck 2016-02-07 05:53:56 +00:00
c7cf86c2ef Sepalated AdditionalHeader class from curl.* 2016-02-07 05:41:56 +00:00
6472eedddc Supported regex type for additional header format. 2016-02-07 05:08:52 +00:00
938554e569 Merge pull request #352 from ggtakec/master
Remove stat file cache dir if specified del_cache - #337
2016-02-07 04:05:45 +09:00
150b83f61e Remove stat file cache dir if specified del_cache - #337 2016-02-06 18:59:13 +00:00
87faed0d04 Merge pull request #351 from ggtakec/master
Check cache dirctory path and attributes - #347
2016-02-06 22:46:16 +09:00
c5a94cfc0c Check cache dirctory path and attributes - #347 2016-02-06 13:38:48 +00:00
f548e8ad5e Merge pull request #348 from RobbKistler/pushtests
Integration test summary, continue on error
2016-02-06 19:06:05 +09:00
203df6b58a Merge pull request #346 from RobbKistler/empty-dir
Fix empty directory check against AWS S3
2016-02-06 18:59:45 +09:00
0ac2f7cded Merge pull request #350 from ggtakec/master
Changed cache out logic for stat - #340
2016-02-06 18:37:58 +09:00
b90b51f2c5 Changed cache out logic for stat - #340 2016-02-06 09:09:17 +00:00
8b457133da Merge pull request #341 from hryang/master
Fix the memory leak issue in fdcache.
2016-02-06 14:41:28 +09:00
7bfaa24d25 Integration test summary, continue on error
Details in README.md and s3fs-integration-test-common.sh

Factor out s3fs-fuse and s3proxy start/stop.  The plan is to make it easier to
add test suites besides small-integration-test.sh that can test with various
s3fs options.

Each test run starts in a uniquely named at the top of the bucket.  This allows
multiple runs against persistent storage without worrying about cleaning
up in error conditions that leave artifiacts behind.

Tests continues if a test case fails.

Results are summarized at the end of the test run

Environment variable to control debug level of s3fs-fuse

Environment variable to enable public bucket (makes it easier to poke
around with tools like curl)

Environment variable to start s3fs-fuse under valgrind

Environment variable that casues script sets up s3fs-fuse and then wait
indefinitely, making it easy to experiment manually with the mount
point.

Additional test case
2016-02-05 05:40:28 -08:00
4eff6b4dd1 Fix empty directory check against AWS S3
For ListBucketResult on an empty directory, AWS S3 and S3Proxy 1.4
differ.  AWS will match the directory name, S3Proxy does not.

Changing max-keys=1 to max-keys-2 works for both implementations.
append_objects_from_xml() will swallow the directory key.  The log
level of this message is changed from ERROR to DBG.

Fixes #345
2016-02-04 23:13:00 -08:00
e3765ad497 Tune the code indent. 2016-01-28 11:16:06 +08:00
dd9f3aed36 Fix the memory leak issue in fdcache. See issue #340 2016-01-28 11:11:53 +08:00
ccfa13f295 Merge pull request #339 from ggtakec/master
Updated README.md for fstab example.
2016-01-24 14:38:48 +09:00
540c04e6cc Updated README.md for fstab example. 2016-01-24 05:34:28 +00:00
4b40727644 Merge pull request #338 from ggtakec/master
Fixed a bug about IAMCRED type could not be retried.
2016-01-24 14:10:39 +09:00
83937700dd Fixed a bug about IAMCRED type could not be retried. 2016-01-24 05:01:50 +00:00
2c156ceea2 Merge pull request #336 from Jirapong/master
update REAME.md for fstab
2016-01-22 00:10:02 +09:00
0615338592 update about netfs on boot 2016-01-19 12:06:10 +07:00
b847872622 update README.md for fstab 2016-01-19 11:22:55 +07:00
e932583309 Merge pull request #334 from andrewgaul/bucket-host
Bucket host should include port and not path
2016-01-17 14:46:40 +09:00
7410b7525f Merge pull request #329 from andrewgaul/v4-signature-get
Correct multiple issues with GET and v4 signing
2016-01-17 14:46:19 +09:00
88a4f04217 Bucket host should include port and not path
This resolves issues when using v4 signing with path-style requests.
2016-01-16 15:58:54 -08:00
ff607e1a2d Correct multiple issues with ListBucketRequest
* provide correct path
* sign query string
* URL encode query string
2016-01-16 10:17:20 -08:00
4bfbfa3621 Merge pull request #331 from andrewgaul/clang
Address various clang warnings
2016-01-16 16:14:50 +09:00
43b91d3235 Merge pull request #330 from andrewgaul/pass-by-reference
Pass by const reference where possible
2016-01-16 16:14:31 +09:00
9fa205f1c3 Merge pull request #328 from andrewgaul/v4-signature-path-request-style
Fix v4 signature with use_path_request_style
2016-01-16 16:14:00 +09:00
e003732f18 Address various clang warnings
Found with:

-Wc++11-extensions
-Wc++11-extra-semi
-Wmissing-variable-declarations
-Wundef
2016-01-11 00:52:24 -08:00
b946b59522 Pass by const reference where possible 2016-01-10 16:58:24 -08:00
ea6b287d1a Fix v4 signature with use_path_request_style
Previously s3fs omitted the bucket name when using path request style
causing SignatureDoesNotMatch with v4 signatures.
2016-01-10 13:41:56 -08:00
a6455ef1bc Merge pull request #323 from andrewgaul/readme
Add goofys to references
2016-01-10 04:26:52 +09:00
8e5e44bfce Add goofys to references 2016-01-07 16:14:11 -08:00
ea151a70c4 Merge pull request #321 from mcellis33/320
320: delete stat cache entry in s3fs_fsync so st_size is refreshed
2015-12-20 15:05:28 +09:00
1e1f2a66de Merge pull request #319 from RobbKistler/clean-exit
Clean up mount point on errors in s3fs_init()
2015-12-20 15:04:54 +09:00
163daa5de1 320: delete stat cache entry in s3fs_fsync so st_size is refreshed 2015-12-18 15:39:25 -08:00
b581290c30 Cleanly exit fuse loop on error in s3fs_init
This allows FUSE to clean the mount point up, preventing
"Transport endpoint not connected" errors on subsequent
access to the mount.
2015-12-15 15:25:56 -08:00
1927ccfe0a Don't loop on fusermount if mountpoint is gone 2015-12-15 15:07:00 -08:00
8162d4925d Merge pull request #313 from mcellis33/gitignore
fix gitignore
2015-12-08 00:04:52 +09:00
2b3ece467b Merge pull request #311 from RobbKistler/dbg-message
Change error log to debug log in s3fs_read()
2015-12-08 00:03:48 +09:00
c2f9b38a95 fix gitignore 2015-12-04 15:21:32 -08:00
8e688816d4 Change error log to debug log in s3fs_read() 2015-12-03 21:25:27 -08:00
8dbd5a3f65 Merge pull request #310 from ggtakec/master
Update integration-test-main.sh as additional change for #300
2015-12-03 22:49:55 +09:00
4bd5ffb0fa Update integration-test-main.sh as additional change for #300 2015-12-03 13:44:43 +00:00
7b2e963636 Merge pull request #300 from bazeli/patch-1
Update integration-test-main.sh
(but it does not work now, I will fix it as soon as possible.)
2015-12-03 22:36:45 +09:00
87d04acb2f Merge pull request #309 from ggtakec/master
Check pthread prtability in configure as additional change for #307
2015-12-03 16:58:23 +09:00
759b44135a Check pthread prtability in configure as additional change for #307 2015-12-03 07:47:17 +00:00
8b53e0d931 Merge pull request #307 from rockuw/master
Fix pthread portability problem
2015-12-03 16:35:30 +09:00
7db23f9d03 Merge pull request #308 from ggtakec/master
Changed ensure free disk space as additional change for #306
2015-12-03 14:49:40 +09:00
3e655bad3b PTHREAD_MUTEX_RECURSIVE_NP is a enum not macro 2015-12-03 13:44:11 +08:00
5e97cb0f48 Changed ensure free disk space as additional change for #306 2015-12-03 05:40:26 +00:00
ef90e0deed Merge pull request #306 from guymguym/patch-1
Fix read concurrency to work in parallel count
2015-12-03 14:26:40 +09:00
f44b61c403 Fix pthread portability problem 2015-12-03 10:44:38 +08:00
Guy
6067af6ef1 Fix read concurrency to work in parallel count
When the prefetch size is limited to the multipart size, the entire parallel logic of the read flow does not have an opportunity to use parallel get.
This fix increases the read performance significantly over our own s3 on-premise solution.
2015-11-30 18:38:15 +02:00
d7a4fc2927 Merge pull request #304 from ggtakec/master
Fixed a bug about mtime - #299
2015-11-30 01:53:13 +09:00
7b62de80f6 Fixed a bug about mtime - #299 2015-11-29 15:53:53 +00:00
8ffff5ba96 Merge remote-tracking branch 'upstream/macosx' 2015-11-29 15:47:47 +00:00
e804441234 Added FAQ wiki page link in README.md 2015-11-26 21:31:03 +09:00
9cc0fd2240 Merge pull request #302 from RobbKistler/syslog-level
Fix syslog level used by S3FS_PRN_EXIT()
2015-11-26 20:35:32 +09:00
fff2952d5f Fix syslog level used by S3FS_PRN_EXIT()
Without converting from s3fs log levels to syslog levels, the syslog
ends up being LOG_EMERG which can cause a broadcast message to all
users.
2015-11-25 13:53:08 -08:00
b85bd53336 Update integration-test-main.sh
new test for mtime preservation copying file with `cp -p`
2015-11-24 17:29:54 +09:00
e1de134d94 Merge branch 'master' into macosx 2015-11-08 06:06:05 +00:00
5af6d4bd82 Merge pull request #295 from ggtakec/fixissue
File opened with O_TRUNC is not flushed - changed #291
2015-11-08 14:14:42 +09:00
c673d9d935 File opened with O_TRUNC is not flushed - changed #291 2015-11-08 04:55:17 +00:00
0fdda61fb5 Merge pull request #293 from SnakeHunt2012/master
Fix a small spelling issue.
2015-11-08 13:26:01 +09:00
331b8456a0 Merge pull request #291 from RobbKistler/truncate
Issue #290: File opened with O_TRUNC is not flushed
2015-11-08 13:23:06 +09:00
63b6f3635b Merge pull request #289 from RobbKistler/log-source-file
Print source file in log messages
2015-11-08 13:14:33 +09:00
c04bcce206 Fix a small spelling issue. 2015-11-06 16:49:37 +08:00
dd7d9268f2 Force flush in s3fs_open() if file is truncated. 2015-11-03 22:06:25 -08:00
a3ef5c820d Add file truncate test
This test creates a file with contents, truncates it to
zero and verifies that it is zero length.
2015-11-03 21:47:15 -08:00
e4da5c59b6 Print source file in log messages 2015-11-03 08:34:02 -08:00
ad2a406205 Merge pull request #288 from ggtakec/master
Fixed a bug about head request(copy) for SSE - issue#286
2015-11-01 23:10:04 +09:00
001206f7c1 Fixed a bug about head request(copy) for SSE - issue#286 2015-11-01 14:05:47 +00:00
2ef7f497f6 Fixed a bug about head request(copy) for SSE - issue#286 2015-11-01 13:54:47 +00:00
497b108109 Merge pull request #285 from andrewgaul/symlink-test
Add test for symlink
2015-11-01 18:46:06 +09:00
86f95b05bf Add test for symlink 2015-10-24 14:20:26 -07:00
70db77af38 Merge pull request #280 from ggtakec/master
Supported a object which is larger than free disk space
2015-10-21 00:53:07 +09:00
8dd234dd8f Fixed bugs about cppcheck error 2015-10-20 15:47:07 +00:00
83d46ef8c6 Fixed bugs about a object larger than free disk space 2015-10-20 15:19:04 +00:00
1b323a6252 Changed debug option to dbglevel in test script. 2015-10-18 17:31:31 +00:00
d102eb752d Supported a object which is larger than free disk space 2015-10-18 17:03:41 +00:00
4252fab685 Merge pull request #248 from andrewgaul/travis-docker
Enable integration tests for Travis
2015-10-19 00:40:28 +09:00
94e3dbb2dc Enable integration tests for Travis
http://blog.travis-ci.com/2015-10-14-opening-up-ubuntu-trusty-beta/
2015-10-14 15:57:15 -07:00
8f115078cd Merge pull request #278 from ggtakec/master
Supported for SSE KMS(#270)
2015-10-07 00:01:38 +09:00
f51ad1f33e Supported for SSE KMS 2015-10-06 14:46:14 +00:00
e29069b8dc Merge pull request #275 from ggtakec/master
Changed and cleaned the logic for debug message.
2015-10-01 05:01:39 +09:00
92e52dadd4 Changed and cleaned the logic for debug message. 2015-09-30 19:41:27 +00:00
a4b00897c1 Merge pull request #274 from ggtakec/master
Modified man page for storage_class option(#271)
2015-09-28 22:52:59 +09:00
f1b7f5ea95 Modified man page for storage_class option(#271) 2015-09-28 13:47:39 +00:00
6a9082f126 Merge pull request #271 from andrewgaul/storage-class
Add support for standard_ia storage class
2015-09-28 22:18:32 +09:00
48f0a6f811 Merge pull request #268 from RobbKistler/loopback
Use 127.0.0.1 not localhost in s3proxy wait loop
2015-09-28 22:12:29 +09:00
1b39b2d450 Merge pull request #267 from nickstinger/master
Added the _netdev option to the fstab example.
2015-09-28 22:11:00 +09:00
785ed642ba Add support for standard_ia storage class
This enables storage with lower at-rest prices, higher request prices,
and lower availability.  Also rework existing reduced redundancy
parsing into a more generic storage class.  More background on
standard_ia:

https://aws.amazon.com/blogs/aws/aws-storage-update-new-lower-cost-s3-storage-option-glacier-price-reduction/
2015-09-17 13:35:25 -07:00
3d5b8a7672 Use 127.0.0.1 not localhost in s3proxy wait loop
localhost doesn't always resolve to 127.0.0.1
2015-09-16 00:06:41 -07:00
0aef0cf765 Added the _netdev option to the fstab example.
Although the network device option (_netdev) may not work everywhere, the option likely does no harm on systems where it's not supported. By adding the option to the example, it will inform users of the necessity for post-network activation and how that might be accomplished.
2015-09-15 10:34:15 +09:00
489f9edec7 Merge pull request #266 from RobbKistler/fix-integration-test
Cleanup from PR #265
2015-09-13 16:44:41 +09:00
718db57ade Code review changes
Missed some cleanup from the code review
2015-09-13 00:31:56 -07:00
639dcf19b0 Merge pull request #265 from RobbKistler/fix-integration-test
Fix integration tests
2015-09-13 15:59:36 +09:00
53bc960224 Merge pull request #263 from RobbKistler/aws
Allow integration testing against Amazon S3
2015-09-13 15:55:28 +09:00
ead346c6d3 Merge pull request #261 from andrewgaul/help-timeouts
Correct help timeouts
2015-09-13 15:49:15 +09:00
375059d9f8 Merge pull request #260 from andrewgaul/help-wrap
Wrap help text at 80 characters
2015-09-13 15:48:28 +09:00
6b21d9d424 Code review changes 2015-09-11 16:09:00 -07:00
dac9844765 Fix remove_nonempty_directory test bug
Wrap the attempt to rmdir in an if statement, otherwise the entire
test process exists (errexit is set). This test expects the rmdir
to fail.
2015-09-11 15:24:17 -07:00
849e66f6a1 Change test_append_file to avoid object read-after-after-overwrite
Open the test file once outside of the tests for loop.  This helps avoid
object consistency problems when running against S3 providers without
strong consistency (like Amazon).  See Issue #263.
2015-09-11 15:24:17 -07:00
6a8a2e4800 Allow integration testing against Amazon S3
Example command line:
S3FS_CREDENTIALS_FILE=keyfile \
TEST_BUCKET_1=somebucket \
S3PROXY_BINARY="" \
URL="http://s3.amazonaws.com" ./small-integration-test.sh
2015-09-11 14:35:12 -07:00
0358908910 Correct help timeouts
Follow-on to #167.
2015-09-10 11:45:05 -07:00
32ce1a7267 Wrap help text at 80 characters 2015-09-10 11:43:09 -07:00
9ea8da839c Merge pull request #258 from juandiegogonzales/patch-1
Update README.md to better explain mount upon boot
2015-09-09 00:15:55 +09:00
39cec488d2 Merge pull request #257 from jesselsteele/patch-1
Update README.md: Bugfix password file permissions errors
2015-09-09 00:15:21 +09:00
96436df18d Merge pull request #256 from andrewgaul/readme
Add no atomic rename to limitations
2015-09-09 00:14:47 +09:00
3aabb5616c Update README.md to better explain mount upon boot
As a novice Linux user, I didn't know I had to add a line into /etc/fstab for automatic mount upon boot. It took me some minutes to research and notice the right process (at first, I even entered s3fs#mybucket into the command line).

This change will (hopefully) save time to unseasoned users.
2015-09-07 10:05:02 -05:00
8e55f45818 Update README.md
received "should not have others permissions" when mounting
did chmod 640 and received "should not have group permissions"
used chmod 600 after creating the password file and had no problems
2015-09-05 15:08:07 +08:00
ec4135c9ed Add no atomic rename to limitations 2015-09-01 13:10:21 -07:00
cfdfecb4d1 Merge pull request #253 from s3fs-fuse/fixmkdirp
Added chacking cache dir perms at starting.
2015-08-23 13:18:50 +09:00
97b8b34aab Added chacking cache dir perms at starting(2). 2015-08-23 04:14:57 +00:00
ce66430fac Added chacking cache dir perms at starting. 2015-08-23 03:57:34 +00:00
1fc56e6665 Merge pull request #252 from Ziggeo/fix-create-cache-directories
This fixes an issue with caching when the creation of a subdirectory …
2015-08-23 10:48:08 +09:00
d7d96907cf This fixes an issue with caching when the creation of a subdirectory within the cache is aborted because a common cached parent directory already exists. 2015-08-21 19:30:04 -04:00
eb97054f49 Merge pull request #251 from flandr/skip-xattr-tests
Skip xattr tests if utilities are missing
2015-08-22 02:11:02 +09:00
7280ca6a69 Skip xattr tests if utilities are missing 2015-08-21 10:05:14 -07:00
30b2a833a8 Merge pull request #250 from s3fs-fuse/issue#228
s3fs can print version with short commit hash - #228
2015-08-22 01:35:07 +09:00
8f8e52b91a s3fs can print version with short commit hash(2) - #228 2015-08-21 16:30:24 +00:00
751c868769 s3fs can print version with short commit hash - #228 2015-08-21 16:19:31 +00:00
c3a47c26ec Merge pull request #249 from andrewgaul/wget-quiet
Silence wget
2015-08-22 00:51:30 +09:00
632578f328 Merge pull request #247 from andrewgaul/base64
Base64 cleanup
2015-08-22 00:45:26 +09:00
5a4240b18d Merge pull request #246 from andrewgaul/coverity
Unlock during early return in TruncateCache
2015-08-22 00:43:34 +09:00
236aeb9dfd Silence wget 2015-08-20 11:38:27 -07:00
bcfadbe1a8 Unlock during early return in TruncateCache
Found via Coverity.  Regression from
dfa63345ed.
2015-08-19 13:54:14 -07:00
b5c027f15d Add unit tests for base64 encoding and decoding 2015-08-19 13:49:10 -07:00
15db80b459 NUL terminate decoded base64 string
For consistency with encoded strings.
2015-08-19 13:48:07 -07:00
76c0ef86e4 Move base64 and hex functions to string_util 2015-08-19 13:47:26 -07:00
a3e820e733 Merge pull request #245 from andrewgaul/map-duplicate-lookups
Elide duplicate lookups of std::map via iterators
2015-08-20 01:22:06 +09:00
a3568a1419 Merge pull request #243 from andrewgaul/cppcheck-travis
Run cppcheck during Travis builds
2015-08-20 01:20:15 +09:00
4ad57bdea5 Merge pull request #240 from andrewgaul/md5
Enable Content-MD5 during multipart upload part
2015-08-20 01:19:01 +09:00
085733d7c9 Merge pull request #239 from andrewgaul/google-code
Update stale Google Code reference in --help
2015-08-20 01:08:00 +09:00
fcb58aec3c Merge pull request #238 from andrewgaul/cppcheck
Enable all cppcheck rules
2015-08-20 01:06:50 +09:00
402c609316 Merge pull request #237 from andrewgaul/test-refactor
Refactor tests into individual functions
2015-08-20 01:03:03 +09:00
026a9f2bdc Merge pull request #235 from andrewgaul/complete-mpu-leak
Plug leak during complete multipart upload
2015-08-20 00:40:00 +09:00
1918d6fa2d Merge pull request #234 from andrewgaul/readme
Update README
2015-08-20 00:37:49 +09:00
fd04b9a437 Merge pull request #233 from andrewgaul/remove-inttostr
Remove IntToStr
2015-08-20 00:34:21 +09:00
ea99603b58 Merge pull request #232 from andrewgaul/stat-cache-locking
Always hold stat_cache_lock when using stat_cache
2015-08-20 00:28:57 +09:00
036612dbb0 Merge pull request #231 from andrewgaul/autolock
Rewrite AutoLock
2015-08-20 00:24:05 +09:00
67d1576dfb Elide duplicate lookups of std::map via iterators
Also remove use of C++11 std::map::at.
2015-08-18 14:00:42 -07:00
2850fe731b Run cppcheck during Travis builds 2015-08-18 03:01:14 -07:00
a157ac59ca Enable Content-MD5 during multipart upload part
This allows retries of multi-part uploads instead of discovering a
fatal error during complete multipart upload.  Also enable Content-MD5
for integration tests and refactor hexadecimal code.
2015-08-18 02:54:00 -07:00
20f425fe15 Update README
This better explains many of the features and limitations and removes
stale information.
2015-08-17 07:48:11 -07:00
32520fd1fb Update stale Google Code reference in --help 2015-08-16 23:30:41 -07:00
c0b21d8808 Enable all cppcheck rules 2015-08-16 17:13:24 -07:00
17d223b542 Refactor tests into individual functions 2015-08-16 15:50:17 -07:00
9c5bf0bb66 Plug leak during complete multipart upload 2015-08-15 22:38:24 -07:00
dfa63345ed Always hold stat_cache_lock when using stat_cache
We could further improve this code by holding stat_cache_lock before
calls to DelStat instead of unlocking then relocking it.
2015-08-14 20:14:12 -07:00
3f59b8da01 Rewrite AutoLock
Previously AutoLock::Lock allowed subsequent callers to proceed
without the lock.  Further is_locked was not always protected by
auto_mutex.  Finally AutoLock eagerly released auto_mutex when
recursively unlocking.  s3fs does not need recursive locks so we
rewrite and simplify AutoLock.  Partially surfaced by Coverity.
2015-08-14 20:00:56 -07:00
0ea88a73c7 Remove IntToStr
str duplicates this functionality.  Also add unit test.
2015-08-12 08:25:09 -07:00
2e344bb48f Merge pull request #229 from andrewgaul/test-rename-before-close
Convert rename_before_close to a shell script
2015-08-13 00:10:07 +09:00
c91a645782 Convert rename_before_close to a shell script #229 2015-08-12 15:09:34 +00:00
96f63a17c0 Merge pull request #224 from andrewgaul/cppcheck
Configure cppcheck
2015-08-13 00:05:31 +09:00
756d1e5e81 Configure cppcheck #224 2015-08-12 15:04:16 +00:00
2482aada43 Merge pull request #222 from andrewgaul/explicit
Annotate constructors as explicit
2015-08-12 23:42:03 +09:00
64146f69a4 Merge pull request #221 from andrewgaul/compare
Compare idiomatically
2015-08-12 23:41:24 +09:00
edb3c78fe9 Merge pull request #220 from andrewgaul/test-rmdir-nonempty-directory
Test removing a non-empty directory
2015-08-12 23:41:08 +09:00
49e32967ec Merge pull request #219 from andrewgaul/coverity
Address Coverity errors
2015-08-12 23:40:47 +09:00
5655cffd32 Merge pull request #217 from jelly/master
Override install, so that the make install does not install rename_before_close under /test
2015-08-12 23:40:18 +09:00
09dff484e1 Merge pull request #215 from RobbKistler/memleak
Fix mem leak in openssl_auth.cpp:s3fs_sha256hexsum
2015-08-12 23:38:51 +09:00
deb0e9eec3 Merge pull request #213 from andrewgaul/rename-large-files
Parse ETag from copy multipart correctly
2015-08-12 23:38:22 +09:00
5d1c8a7eda Convert rename_before_close to a shell script 2015-08-11 20:51:18 -07:00
ff8a0c2eea Parse ETag from copy multipart correctly
Previously s3fs misparsed this, preventing renames of files larger
than 5 GB.  Integration test disabled until S3Proxy 1.5.0 is released.
2015-08-11 14:43:35 -07:00
cbf7777f41 Configure cppcheck 2015-08-08 05:18:51 -07:00
fcb55c2109 Fix mem leaks in openssl_auth.cpp, nss_auth.cpp
Fix memory leaks in openssl_auth.cpp:s3fs_sha256hexsum and
nss_auth.cpp:s3fs_sha256hexsum.  Leaks occur every time a file
is created.
2015-08-06 12:45:40 -07:00
b6fa2deb9f Annotate constructors as explicit
This prevents implicit conversions.
2015-08-05 23:41:53 -07:00
801ca0c2d3 Compare idiomatically 2015-08-05 23:35:08 -07:00
5f792a9a2b Test removing a non-empty directory 2015-08-05 23:31:13 -07:00
8ee71caabb Address Coverity errors
Fixed an uninitialized member, misordered NULL check, resource leak,
and unconsumed return value.
2015-08-05 23:28:06 -07:00
ed70f7763a Override install, so that the make install does not install
rename_before_close under /test
2015-08-01 17:15:00 +02:00
730262f000 Merge pull request #212 from s3fs-fuse/master
update content of the master to macosx branch.
2015-07-20 01:38:42 +09:00
cbc057bca7 Merge pull request #211 from s3fs-fuse/release179
Updated ChangeLog and configure.ac for v1.79
2015-07-20 01:23:35 +09:00
6442642656 Updated ChangeLog and configure.ac for v1.79 2015-07-19 16:14:33 +00:00
07a5a36b6a Merge pull request #207 from jalessio/fix_a_few_spelling_issues
Fixed a few small spelling issues.
2015-07-12 01:02:53 +09:00
912bc58df0 Fixed a few small spelling issues. 2015-07-10 11:50:40 -07:00
13a91a52e8 Merge pull request #204 from andrewgaul/xattr-test
Add integration test for xattr
2015-06-29 00:51:24 +09:00
4190130194 Merge pull request #202 from flandr/osx-xattr
Specialize {set,get}xattr for OS X
2015-06-29 00:29:57 +09:00
d9b124f91e Add integration test for xattr 2015-06-28 04:16:35 -07:00
9b3c87ec97 Specialize {set,get}xattr for OS X
These system calls take an extra 'position' parameter on OS X. A
non-zero position value is only valid for resource forks (the Darwin
VFS layer will reject anything else with EINVAL); this patch simply
adds and ignores the parameter on Apple platforms.

Allows building against OSXFUSE.
2015-06-25 12:56:15 -07:00
8f85e5e543 Merge pull request #200 from s3fs-fuse/fixbug
fixed fallback to sigv2 for bucket create and GCS
2015-06-20 13:45:45 +09:00
966d229787 fixed fallback to sigv2 for bucket create and GCS 2015-06-20 04:34:32 +00:00
4d49ace06b Merge pull request #192 from andrewgaul/special-characters
Simplify URL encoding
2015-06-20 11:47:22 +09:00
ad8c64104e Merge pull request #199 from s3fs-fuse/xattr
Supported extended attributes(retry)
2015-06-20 11:46:47 +09:00
d59eff4288 Merge pull request #198 from andrewgaul/travis
Disasble integration tests for Travis
2015-06-20 10:42:23 +09:00
219b155037 Disasble integration tests for Travis
The previous KVM infrastructure supported this but their new VMware
infrastructure does not.
2015-06-18 11:28:10 -07:00
fe3abed9f0 Chaged codes about iterator etc 2015-06-13 03:27:07 +00:00
0ecf4aa6b4 Chaged codes about iterator 2015-06-13 03:08:56 +00:00
477573265a Merge pull request #190 from Rotwang/master
Add a no_check_certificate option.
2015-06-13 11:12:35 +09:00
4e03acf17a Simplify URL encoding
This also encodes asterisk and tilde correctly when listing a file
with a V4 auth endpoint.  Also add tests for special characters
although s3proxy does not yet support V4 auth.
Fixes #188.  Fixes #194.
2015-06-10 13:15:58 -07:00
84fb3d83d8 Fixed xattr for binary value 2015-06-06 16:39:39 +00:00
3522e5eda3 Add no_check_certificate option which allows to ignore issues with self signed certs. 2015-05-20 17:32:36 +02:00
3056644969 Merge pull request #185 from andrewgaul/typos
Correct obvious typos in usage and README
2015-05-06 22:37:22 +09:00
91587ad2c8 Merge pull request #184 from andrewgaul/multipart-size
Add usage information for multipart_size
2015-05-06 22:36:37 +09:00
8a73d9fff0 Correct obvious typos in usage and README 2015-05-04 16:25:05 -07:00
28ee9f27b9 Add usage information for multipart_size
Also improve error message.
2015-05-04 16:21:58 -07:00
7ac58a1c69 Merge pull request #178 from andrewgaul/gitignore
Update .gitignore
2015-04-29 00:56:54 +09:00
3914281f1b Merge pull request #177 from andrewgaul/mailmap
Add .mailmap
2015-04-29 00:56:44 +09:00
3d734ad3e3 Merge pull request #176 from mooredan/master
configure.ac: detect target, if target is darwin (OSX), then
2015-04-29 00:55:35 +09:00
bb4075d7b9 Merge pull request #173 from andrewgaul/travis
Run integration tests via Travis
2015-04-29 00:54:14 +09:00
5b11ac0f4c Moved __APPLE__ #endif to correct position 2015-04-27 12:14:09 -07:00
7bc5f0ca13 Update .gitignore 2015-04-27 11:19:14 -07:00
14ce061215 Add .mailmap
This cleans up git shortlog output.
2015-04-27 11:17:39 -07:00
adb5a35097 configure.ac: detect target, if target is darwin (OSX), then
change the minimum version of fuse required.  Change the
checkers to use a variable for the minimum fuse version
instead of it being hardcoded in four different places.

src/s3fs.cpp: Use __APPLE__ define around fuse code that
is offensive to osxfuse. Not including the code doesn't
seem to matter.
2015-04-25 17:13:20 -07:00
b0a12bcac1 Disable rename_before_close
This test currently fails and interferes with the larger integration
test.  References #145.
2015-04-24 11:28:18 -07:00
39d4715b82 Run integration tests via Travis
Mail from the Travis team:

Thanks for the email. I have set up s3fs-fuse/s3fs-fuse with our alpha
testing stack which may allow you to use FUSE.

To use it, add the following to your .travis.yml:
dist: trusty

Please keep in mind that the service may become unavailable without
notice, and change details. We welcome your feedback as to what works
and what does not with this setup.
2015-04-23 21:25:24 -07:00
aac92bd6c0 Fixed wrong owner checking and return codes 2015-04-21 16:18:05 +00:00
f258a14070 Supported extended attributes, initial commit 2015-04-20 17:24:57 +00:00
3701f1c16b Merge pull request #171 from pabigot/mixedcase
Support buckets with mixed-case names
2015-04-21 02:06:07 +09:00
92fcee824b curl: use pathrequeststyle option when constructing Host endpoint
Buckets with mixed-case names can't be accessed with the virtual-hosted
style API due to DNS limitations.  S3FS has an option for
pathrequeststyle which is used for the URL, but it was not applied when
building the endpoint passed through the Host header.  Fix this, and
relax the validation on bucket names when using this style.

See: http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingBucket.html#access-bucket-intro

Signed-off-by: Peter A. Bigot <pab@pabigot.com>
2015-04-19 08:31:40 -05:00
00f8e1d0ba Merge pull request #170 from s3fs-fuse/issue/#157
Reviewed and fixed response codes print in curl.cpp - #157
2015-04-18 23:37:28 +09:00
43191eea53 Added cache apt in travis.yml 2015-04-18 13:45:58 +00:00
490ed8f689 Reviewed and fixed response codes print in curl.cpp - #157 2015-04-18 13:32:04 +00:00
30152284cc Merge pull request #168 from kahing/fix-v4-host-endpoint
switch to use region specific endpoints to compute correct v4 signature
2015-04-18 18:02:45 +09:00
70097709b2 switch to use region specific endpoints to compute correct v4 signature
fix #133
2015-04-14 16:25:17 -07:00
07e007052a Merge pull request #167 from s3fs-fuse/timeoutbranch
Increased default connecting/reading/writing timeout value
2015-04-12 11:18:52 +09:00
bd27294ab0 Increased default connecting/reading/writing timeout value 2015-04-12 02:04:13 +00:00
5e5c20757b Merge pull request #165 from kahing/auth_v4_refactor
Auth v4 refactor
2015-04-12 08:13:25 +09:00
6231ae208a Merge pull request #164 from kahing/fix_v4_signing_host
send the correct Host header when using -o url
2015-04-12 08:12:51 +09:00
42a4f5fd95 Merge pull request #159 from andrewgaul/s3proxy-1.4.0
Upgrade to S3Proxy 1.4.0
2015-04-12 08:05:49 +09:00
6e0a302f7d refactor sigv4 to reduce code duplication 2015-04-09 15:11:59 -07:00
98af055d8b send the correct Host header when using -o url
fixes #161
2015-04-09 13:53:50 -07:00
fa5c7ff4df Upgrade to S3Proxy 1.4.0
Release notes:

https://github.com/andrewgaul/s3proxy/releases/tag/s3proxy-1.4.0
2015-03-29 23:59:39 -07:00
d7327df885 Merge pull request #156 from s3fs-fuse/issue/#126
Fixed a bug about ssl session sharing with libcurl older 7.23.0 - issue#126
2015-03-21 16:19:58 +09:00
0f13c8fe97 Fixed a bug about ssl session sharing with libcurl older 7.23.0 - issue/#126 2015-03-21 07:04:20 +00:00
44d740080b Merge pull request #155 from s3fs-fuse/bugfix
Fixed a bug: unable to mount bucket subdirectory
2015-03-21 13:39:19 +09:00
2fc3a4e91e Fixed a bug: unable to mount bucket subdirectory 2015-03-21 04:31:59 +00:00
66e0233410 Merge pull request #154 from s3fs-fuse/issue#149
Fixed url-encoding for ampersand etc on sigv4 - Improvement/#149
2015-03-21 11:32:08 +09:00
a04bec85b2 Fixed url-encoding for ampersand etc on sigv4 - Improvement/#149 2015-03-21 02:11:55 +00:00
f861b11a91 Merge pull request #147 from andrewgaul/s3proxy-snapshot
Use S3Proxy 1.4.0-SNAPSHOT
2015-03-11 01:41:58 +09:00
37f9bbd231 Merge pull request #146 from kahing/exit_handler_for_test
add exit handler to cleanup on failures
2015-03-11 01:41:42 +09:00
af004576f1 Merge pull request #150 from s3fs-fuse/fixbug
Fixed a bug not handling fsync - #145
2015-03-11 01:29:17 +09:00
26453c4874 Fixed a bug not handling fsync. 2015-03-10 16:18:03 +00:00
4e18bf0bc2 Use S3Proxy 1.4.0-SNAPSHOT 2015-03-09 18:05:14 -07:00
7c298e94f5 add exit handler to cleanup on failures
and other changes that make debugging easier
2015-03-09 15:56:38 -07:00
761d2399f2 Merge pull request #144 from andrewgaul/travis
Add Travis configuration
2015-03-10 01:37:50 +09:00
1210cf8c6c Add Travis configuration 2015-03-09 03:57:39 -07:00
524e005b5c Merge pull request #143 from s3fs-fuse/issue#141
Fixed a bug no use_cache case about fixed #138 - issue#141
2015-03-09 01:43:57 +09:00
d06b6d7d41 Fixed a bug no use_cache case about fixed #138 - issue#141 2015-03-08 16:41:14 +00:00
e66e5d1dfc Merge pull request #138 from s3fs-fuse/issue#97
Fixed bugs, not turn use_cache off and ty to load to end - issue#97
2015-03-04 17:52:22 +09:00
114966e7c0 Fixed bugs, not turn use_cache off and ty to load to end - issue#97 2015-03-04 08:48:37 +00:00
d2246297bd Merge pull request #137 from andrewgaul/integration-test-mpu
Add test for multi-part upload
2015-03-04 12:21:22 +09:00
8ec5decbce Merge pull request #136 from andrewgaul/integration-test-fixups
Small fixes to integration tests
2015-03-04 12:20:17 +09:00
0f7d77d599 Small fixes to integration tests
Use S3Proxy pid instead of self pid, ensure correct passwd
permissions, and use fusermount instead of umount so that non-root can
run tests.
2015-03-03 01:42:03 -08:00
699e3b3d79 Add test for multi-part upload 2015-03-02 17:17:30 -08:00
2f8ad7ace8 Merge pull request #135 from andrewgaul/mpu-v4
Correct V4 signature for initiate multipart upload
2015-03-01 22:57:10 +09:00
6b6567ec9b Merge pull request #134 from andrewgaul/mpu-v2
Include Content-Type in complete MPU V2 signature
2015-03-01 22:50:54 +09:00
c8c71650eb Merge pull request #131 from kahing/test-ls
Test ls
2015-03-01 22:47:55 +09:00
a07e804f57 Include Content-Type in complete MPU V2 signature
Previously this failed with SignatureDoesNotMatch since the headers
included it but the signature did not.  Fixes #125.
2015-02-28 18:03:21 -08:00
e9656810e3 Correct V4 signature for initiate multipart upload
Query parameters need a trailing = for V4 signatures.  Send correct
content-sha256 although Amazon does not seem to enforce this for
zero-length bodies.  Finally remove a stale comment.  Fixes #133.
2015-02-28 17:50:06 -08:00
4ee32d7559 test ls after creating files and dirs 2015-02-27 10:55:25 -08:00
53083202ba Merge pull request #132 from andrewgaul/s3proxy-integration-test
Use S3Proxy to run integration tests
2015-02-27 00:17:46 +09:00
574a48f81f Merge pull request #130 from kahing/refactor-integration-test
refactor integration tests create/cleanup file
2015-02-27 00:06:23 +09:00
1b1cf2d4bd Merge pull request #124 from timuralp/bug/fix_fallback_v2
Fallback to v2 signatures correctly.
2015-02-27 00:02:12 +09:00
e811ae1104 Use s3proxy to run integration tests
References #129.
2015-02-24 12:08:22 -08:00
d65bf4128d refactor integration tests create/cleanup file 2015-02-23 12:08:14 -08:00
be5735edb8 Fallback to v2 signatures correctly.
Missing parameter to SetSignatureV4() call in the fallback code path
results in not actually falling back.
2015-02-16 17:35:09 -08:00
5bf2b46fa3 Merge pull request #119 from s3fs-fuse/issue#107
Added new mp_umask option about issue#107, pr#110
2015-02-08 02:19:54 +09:00
cf2b0cca22 Added new mp_umask option about issue#107, pr#110 2015-02-07 17:16:45 +00:00
4ae5043534 Merge pull request #116 from s3fs-fuse/dev_sv4
Supported signature version 4
2015-02-03 01:43:48 +09:00
1424f87754 Supported signature version 4 for GnuTLS/NSS and automatically set endpoint/sigv2 2015-02-02 16:36:08 +00:00
4f953f9bd7 Clean codes for signature v4 and added new sigv2 option 2015-01-28 17:13:11 +00:00
0d2f3e2dc4 Fixed bugs, segfault and signature error at listing. 2015-01-24 16:36:30 +00:00
bb1f1d3faa Merged manually from caxapniy/s3fs-fuse/tree/1.77v4merge for signature v4 - #102 2015-01-20 16:31:36 +00:00
98daf16681 Merge pull request #104 from kahing/rename_before_close
fix rename before close
2015-01-14 00:40:41 +09:00
939ba2b4b3 Merge pull request #101 from adobos/directory_empty_optimization
Optimized function "bool directory_empty()"
2015-01-14 00:21:47 +09:00
d0b82428d5 Merge pull request #100 from adobos/dns_ssl_switch_bugfix
CURL handles not properly initialized to use DNS or SSL session caching.
2015-01-14 00:11:46 +09:00
902911765e Merge pull request #93 from andrewgaul/unit-test
Add simple unit tests for trim functions
2015-01-14 00:07:01 +09:00
03d84a07d1 fix rename before close
nautilus does this when you drag and drop to overwrite a file:

1) create .goutputstream-XXXXXX to write to
2) fsync the fd for .goutputstream-XXXXXX
3) rename .goutputstream-XXXXXX to target file
4) close the fd for .goutputstream-XXXXXX

previously, doing this on s3fs would result in an empty target file
because after the rename, s3fs would not flush the content of
.goutputstream-XXXXXX to target file.

this change moves the FdEntity from the old path to the new path
whenever rename happens. On flush s3fs would now flush the correct
content to the rename target.
2015-01-12 15:05:54 -08:00
1f686d93ff Merge pull request #103 from s3fs-fuse/issue#87
Remove prefix option in s3fs man page - issue#87
2015-01-06 23:49:11 +09:00
d95b9ef1ac Remove prefix option in s3fs man page - issue#87 2015-01-06 14:43:19 +00:00
045f1e7906 CURL handles were not properly initialized to use DNS caching, or SSL session caching. 2014-12-23 22:31:54 -08:00
69ef7fbefb Optimized function directory_empty: check for at most one entry when evaluating whether a directory is empty or not (as opposed to doing full directory listing) 2014-12-23 22:29:13 -08:00
a56b8db410 Add simple unit tests for trim functions
Subsequent commits will use this infrastructure.  Also reparent
prepare_url which relies on unrelated bucket, foreground2, and
pathrequeststyle symbols.
2014-12-06 18:07:14 -08:00
082eb24c12 Merge pull request #83 from tmwong2003/develop
Changed option processing to use strtol() to get a umask
2014-11-16 23:49:24 +09:00
f04b659f5e Changed option processing to use strtol() to get a umask
get_mode()/s3fs_strtoofft() does not handle octal umask values, which
results in unexpected behavior when trying to set a world-readable umask
value.
2014-11-12 23:29:41 +00:00
eedc621637 Merge pull request #79 from buptUnixGuys/master
Update curl.cpp
2014-11-09 00:05:04 +09:00
b31ec5c4af Update curl.cpp
The space causes signature mismatch when using "ahbe_conf" file to add additional headers.When s3 use the" x-amaz" header to calculates the signature, the format is as follow:
PUT

application/octet-stream
Wed, 05 Nov 2014 03:05:08 GMT
x-amz-acl:private
x-amz-meta-gid:0
x-amz-meta-mode:33188
x-amz-meta-mtime:1415156708
x-amz-meta-uid:0
There is no space after colon.
2014-11-05 11:28:33 +08:00
651e8c3158 Merge pull request #64 from andrewgaul/failed-read-eio
Return EIO on failed read
2014-11-03 01:03:32 +09:00
77d4d066b5 Merge pull request #74 from vincentbernat/fix/url-may-omit-scheme
url: handle scheme omission
2014-10-26 16:18:03 +09:00
1e97e99aa0 Merge pull request #73 from vincentbernat/fix/git-ignore
Small gitignore fixes
2014-10-26 16:12:44 +09:00
7212072ff0 url: handle scheme omission
When the scheme is omitted in URL overriding (for example `example.com`
instead of `https://example.com`), s3fs is modifying the URL by
inserting `s3.` in the middle of the name  (`examples3..com`).

This can be a bit difficult to troubleshoot and curl seems to handle
schema-less requests just fine. So, just handle this case correctly.
2014-10-23 10:25:17 +02:00
8bcab645e1 gitignore: add test-driver and compile
Those are generated by latest versions of autotools.
2014-10-23 10:02:59 +02:00
9013917d58 gitignore: use absolute path
The current content of `.gitignore` is using relative paths. For
example, `test/config.log` would be ignored while it doesn't seem to be
the intent. Use absolute paths. They are still relative to the root of
the repository.
2014-10-23 10:01:08 +02:00
1eddf92c35 Merge pull request #72 from s3fs-fuse/issue#68
Fixed #68(FreeBSD issue)
2014-10-22 23:30:32 +09:00
28d82c9ccd Fixed #68(FreeBSD issue) 2014-10-22 14:21:01 +00:00
2f90a04513 Merge pull request #71 from s3fs-fuse/issue#68
Fixed for #68(FreeBSD issue)
2014-10-21 23:58:20 +09:00
2724728476 Merge pull request #70 from s3fs-fuse/master
Fixed for #68(FreeBSD issue)
2014-10-21 23:56:41 +09:00
ed8f424c1a Merge pull request #69 from andrewgaul/always-true
Address clang always true warnings
2014-10-21 23:53:30 +09:00
50137fe026 Address clang always true warnings 2014-10-16 23:34:12 -07:00
9237d07226 Merge pull request #63 from jollyroger/spelling
Fix spelling errors
2014-10-13 11:38:13 +09:00
8c2be4aa85 Merge pull request #62 from jollyroger/fix-stray-chars
Remove stray chars from source files
2014-10-13 11:34:52 +09:00
ccaed9a91c Merge pull request #60 from andrewgaul/check-bucket-disable-fail-on-error
Emit user-friendly log messages on failed CheckBucket requests
2014-10-13 11:33:17 +09:00
a1ca8b7124 Return EIO on failed read
Previously S3fsMultiCurl::MultiRead did not report read errors since
it did not treat failed callback setup as a fatal operation error.
Failed callback setups usually result from exceeding the number of
allowed retries.  Previously cp did not report an error during a
network outage but now does:

$ cp ~/s3-path/s3-file .
cp: error reading ‘/home/gaul/s3-path/s3-file’: Input/output error
cp: failed to extend ‘./s3-file’: Input/output error
2014-10-03 21:30:11 -07:00
6633366218 Fix spelling errors 2014-10-01 13:42:39 +03:00
22ea65f02c Remove stray chars from source files 2014-10-01 13:20:29 +03:00
3d69ee0c30 Emit response on failed CheckBucket requests
This allows callers to diagnose errors like InvalidAccessKeyId and
RequestTimeTooSkewed.
2014-09-28 16:12:53 -07:00
c88a5f38be Disable CURLOPT_FAILONERROR for CheckBucket
curl will not consume the body of a response when CURLOPT_FAILONERROR
is set.  This prevents logging of responses for failed requests.
2014-09-28 16:12:43 -07:00
38e6857824 Merge pull request #56 from s3fs-fuse/version1.78
version number increament.
2014-09-15 22:30:51 +09:00
ca72b9a6d0 version number increament. 2014-09-15 13:26:35 +00:00
105 changed files with 27802 additions and 10922 deletions

39
.clang-tidy Normal file
View File

@ -0,0 +1,39 @@
Checks: '
-*,
bugprone-*,
-bugprone-branch-clone,
-bugprone-macro-parentheses,
-bugprone-narrowing-conversions,
-bugprone-unhandled-self-assignment,
google-*,
-google-build-using-namespace,
-google-readability-casting,
-google-readability-function-size,
-google-readability-todo,
-google-runtime-int,
-google-runtime-references,
misc-*,
-misc-no-recursion,
-misc-redundant-expression,
-misc-unused-parameters,
modernize-*,
-modernize-avoid-c-arrays,
-modernize-deprecated-headers,
-modernize-loop-convert,
-modernize-use-auto,
-modernize-use-nullptr,
-modernize-use-trailing-return-type,
-modernize-use-using,
performance-*,
-performance-no-int-to-ptr,
portability-*,
readability-*,
-readability-else-after-return,
-readability-function-cognitive-complexity,
-readability-function-size,
-readability-implicit-bool-conversion,
-readability-inconsistent-declaration-parameter-name,
-readability-isolate-declaration,
-readability-magic-numbers,
-readability-named-parameter,
-readability-simplify-boolean-expr'

32
.gitattributes vendored Normal file
View File

@ -0,0 +1,32 @@
#
# s3fs - FUSE-based file system backed by Amazon S3
#
# Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
#
# 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.
#
* text eol=lf
*.png binary
#
# Local variables:
# tab-width: 4
# c-basic-offset: 4
# End:
# vim600: noet sw=4 ts=4 fdm=marker
# vim<600: noet sw=4 ts=4
#

28
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,28 @@
### Additional Information
_The following information is very important in order to help us to help you. Omission of the following details may delay your support request or receive no attention at all._
_Keep in mind that the commands we provide to retrieve information are oriented to GNU/Linux Distributions, so you could need to use others if you use s3fs on macOS or BSD_
#### Version of s3fs being used (s3fs --version)
_example: 1.00_
#### Version of fuse being used (pkg-config --modversion fuse, rpm -qi fuse, dpkg -s fuse)
_example: 2.9.4_
#### Kernel information (uname -r)
_command result: uname -r_
#### GNU/Linux Distribution, if applicable (cat /etc/os-release)
_command result: cat /etc/os-release_
#### s3fs command line used, if applicable
```
```
#### /etc/fstab entry, if applicable
```
```
#### s3fs syslog messages (grep s3fs /var/log/syslog, journalctl | grep s3fs, or s3fs outputs)
_if you execute s3fs with dbglevel, curldbg option, you can get detail debug messages_
```
```
### Details about issue

5
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,5 @@
### Relevant Issue (if applicable)
_If there are Issues related to this PullRequest, please list it._
### Details
_Please describe the details of PullRequest._

188
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,188 @@
#
# s3fs - FUSE-based file system backed by Amazon S3
#
# Copyright(C) 2007 Takeshi Nakatani <ggtakec.com>
#
# 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.
#
name: s3fs-fuse CI
on:
push:
pull_request:
#
# CRON event is fire on every sunday(UTC).
#
schedule:
- cron: '0 0 * * 0'
#
# Jobs
#
# [NOTE]
# Some tests using awscli may output a python warning.
# The warning is about HTTPS connections using self-signed certificates.
# That's why the PYTHONWARNINGS environment variable disables the
# "Unverified HTTPS request" warning.
#
jobs:
Linux:
runs-on: ubuntu-latest
#
# build matrix for containers
#
strategy:
#
# do not stop jobs automatically if any of the jobs fail
#
fail-fast: false
#
# matrix for containers
#
matrix:
container:
- ubuntu:21.04
- ubuntu:20.04
- ubuntu:18.04
- ubuntu:16.04
- debian:buster
- debian:stretch
- centos:centos8
- centos:centos7
- fedora:34
- opensuse/leap:15
container:
image: ${{ matrix.container }}
options: "--privileged --cap-add SYS_ADMIN --device /dev/fuse"
env:
# [NOTE]
# Installation special environment variables for debian and ubuntu.
#
DEBIAN_FRONTEND: noninteractive
# [NOTE]
# Since using a self-signed certificate and have not registered a certificate authority,
# we get a warning in python, so we suppress it(by PYTHONWARNINGS).
#
PYTHONWARNINGS: "ignore:Unverified HTTPS request"
steps:
# [NOTE]
# On openSUSE, tar and gzip must be installed before action/checkout.
#
- name: Install packages before checkout
run: |
if [ "${{ matrix.container }}" = "opensuse/leap:15" ]; then zypper install -y tar gzip; fi
- name: Checkout source code
uses: actions/checkout@v2
# [NOTE]
# Matters that depend on OS:VERSION are determined and executed in the following script.
# Please note that the option to configure (CONFIGURE_OPTIONS) is set in the environment variable.
#
- name: Install pacakagse
run: |
.github/workflows/linux-ci-helper.sh ${{ matrix.container }}
- name: Build
run: |
./autogen.sh
/bin/sh -c "./configure ${CONFIGURE_OPTIONS}"
make
- name: Cppcheck
run: |
make cppcheck
- name: Test suite
run: |
make ALL_TESTS=1 check -C test || (test/filter-suite-log.sh test/test-suite.log; exit 1)
# [NOTE]
# A case of "runs-on: macos-11.0" does not work,
# becase load_osxfuse returns exit code = 1.
# Maybe it needs to reboot. Apple said
# "Installing a new kernel extension requires signing in as an Admin user. You must also restart your Mac to load the extension".
# Then we do not use macos 11 on Github Actions now.
#
macos10:
runs-on: macos-10.15
env:
# [NOTE]
# Since using a self-signed certificate and have not registered a certificate authority,
# we get a warning in python, so we suppress it(by PYTHONWARNINGS).
#
PYTHONWARNINGS: "ignore:Unverified HTTPS request"
steps:
- name: Checkout source code
uses: actions/checkout@v2
- name: Brew tap
run: |
TAPS="$(brew --repository)/Library/Taps";
if [ -e "$TAPS/caskroom/homebrew-cask" ]; then rm -rf "$TAPS/caskroom/homebrew-cask"; fi;
HOMEBREW_NO_AUTO_UPDATE=1 brew tap homebrew/homebrew-cask
- name: Install osxfuse
run: |
HOMEBREW_NO_AUTO_UPDATE=1 brew install osxfuse
- name: Install brew other packages
run: |
S3FS_BREW_PACKAGES='automake cppcheck python3 coreutils gnu-sed';
for s3fs_brew_pkg in ${S3FS_BREW_PACKAGES}; do if brew list | grep -q ${s3fs_brew_pkg}; then if brew outdated | grep -q ${s3fs_brew_pkg}; then HOMEBREW_NO_AUTO_UPDATE=1 brew upgrade ${s3fs_brew_pkg}; fi; else HOMEBREW_NO_AUTO_UPDATE=1 brew install ${s3fs_brew_pkg}; fi; done;
- name: Install awscli
run: |
if pip3 --version; then pip3 install awscli; else curl https://bootstrap.pypa.io/get-pip.py | sudo python; pip install awscli --ignore-installed matplotlib; fi
- name: Check osxfuse permission
run: |
if [ -f /Library/Filesystems/osxfusefs.fs/Support/load_osxfusefs ]; then sudo chmod +s /Library/Filesystems/osxfusefs.fs/Support/load_osxfusefs; elif [ -f /Library/Filesystems/osxfuse.fs/Contents/Resources/load_osxfuse ]; then sudo chmod +s /Library/Filesystems/osxfuse.fs/Contents/Resources/load_osxfuse; else exit 1; fi
- name: Build
run: |
./autogen.sh
PKG_CONFIG_PATH=/usr/local/opt/curl/lib/pkgconfig:/usr/local/opt/openssl/lib/pkgconfig ./configure CXXFLAGS='-std=c++03 -DS3FS_PTHREAD_ERRORCHECK=1'
make
- name: Cppcheck
run: |
make cppcheck
- name: Test suite
run: |
make check -C src
echo "user_allow_other" | sudo tee -a /etc/fuse.conf >/dev/null
if [ -f /Library/Filesystems/osxfusefs.fs/Support/load_osxfusefs ]; then /Library/Filesystems/osxfusefs.fs/Support/load_osxfusefs; elif [ -f /Library/Filesystems/osxfuse.fs/Contents/Resources/load_osxfuse ]; then /Library/Filesystems/osxfuse.fs/Contents/Resources/load_osxfuse; else exit 1; fi
make ALL_TESTS=1 check -C test || (test/filter-suite-log.sh test/test-suite.log; exit 1)
#
# 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
#

218
.github/workflows/linux-ci-helper.sh vendored Executable file
View File

@ -0,0 +1,218 @@
#!/bin/sh
#
# s3fs - FUSE-based file system backed by Amazon S3
#
# Copyright(C) 2007 Takeshi Nakatani <ggtakec.com>
#
# 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.
#
echo "${PRGNAME} [INFO] Start Linux helper for installing packages."
#-----------------------------------------------------------
# Common variables
#-----------------------------------------------------------
PRGNAME=`basename $0`
#-----------------------------------------------------------
# Parameter check
#-----------------------------------------------------------
#
# Usage: ${PRGNAME} "OS:VERSION"
#
if [ $# -ne 1 ]; then
echo "${PRGNAME} [ERROR] No container name options specified."
fi
#-----------------------------------------------------------
# Container OS variables
#-----------------------------------------------------------
CONTAINER_FULLNAME=$1
CONTAINER_OSNAME=`echo ${CONTAINER_FULLNAME} | sed 's/:/ /g' | awk '{print $1}'`
CONTAINER_OSVERSION=`echo ${CONTAINER_FULLNAME} | sed 's/:/ /g' | awk '{print $2}'`
#-----------------------------------------------------------
# Common variables for pip
#-----------------------------------------------------------
PIP_BIN="pip3"
PIP_OPTIONS="--upgrade"
INSTALL_AWSCLI_PACKAGES="awscli"
#-----------------------------------------------------------
# Parameters for configure(set environments)
#-----------------------------------------------------------
CONFIGURE_OPTIONS="CXXFLAGS='-std=c++11 -DS3FS_PTHREAD_ERRORCHECK=1' --prefix=/usr --with-openssl"
#-----------------------------------------------------------
# OS dependent variables
#-----------------------------------------------------------
if [ "${CONTAINER_FULLNAME}" = "ubuntu:21.04" ]; then
PACKAGE_MANAGER_BIN="apt-get"
PACKAGE_UPDATE_OPTIONS="update -y -qq"
INSTALL_PACKAGES="autoconf autotools-dev fuse libfuse-dev libcurl4-openssl-dev libxml2-dev locales-all mime-support libtool pkg-config libssl-dev attr wget python2 python3-pip"
INSTALL_CPPCHECK_OPTIONS=""
INSTALL_JDK_PACKAGES="openjdk-8-jdk"
elif [ "${CONTAINER_FULLNAME}" = "ubuntu:20.04" ]; then
PACKAGE_MANAGER_BIN="apt-get"
PACKAGE_UPDATE_OPTIONS="update -y -qq"
INSTALL_PACKAGES="autoconf autotools-dev fuse libfuse-dev libcurl4-openssl-dev libxml2-dev locales-all mime-support libtool pkg-config libssl-dev attr wget python2 python3-pip"
INSTALL_CPPCHECK_OPTIONS=""
INSTALL_JDK_PACKAGES="openjdk-8-jdk"
elif [ "${CONTAINER_FULLNAME}" = "ubuntu:18.04" ]; then
PACKAGE_MANAGER_BIN="apt-get"
PACKAGE_UPDATE_OPTIONS="update -y -qq"
INSTALL_PACKAGES="autoconf autotools-dev fuse libfuse-dev libcurl4-openssl-dev libxml2-dev locales-all mime-support libtool pkg-config libssl-dev attr wget python3-pip"
INSTALL_CPPCHECK_OPTIONS=""
INSTALL_JDK_PACKAGES="openjdk-8-jdk"
elif [ "${CONTAINER_FULLNAME}" = "ubuntu:16.04" ]; then
PACKAGE_MANAGER_BIN="apt-get"
PACKAGE_UPDATE_OPTIONS="update -y -qq"
INSTALL_PACKAGES="autoconf autotools-dev fuse libfuse-dev libcurl4-openssl-dev libxml2-dev locales-all mime-support libtool pkg-config libssl-dev attr wget python3-pip"
INSTALL_CPPCHECK_OPTIONS=""
INSTALL_JDK_PACKAGES="openjdk-8-jdk"
elif [ "${CONTAINER_FULLNAME}" = "debian:buster" ]; then
PACKAGE_MANAGER_BIN="apt-get"
PACKAGE_UPDATE_OPTIONS="update -y -qq"
INSTALL_PACKAGES="autoconf autotools-dev fuse libfuse-dev libcurl4-openssl-dev libxml2-dev locales-all mime-support libtool pkg-config libssl-dev attr wget python2 procps python3-pip"
INSTALL_CPPCHECK_OPTIONS=""
INSTALL_JDK_PACKAGES="adoptopenjdk-8-hotspot"
elif [ "${CONTAINER_FULLNAME}" = "debian:stretch" ]; then
PACKAGE_MANAGER_BIN="apt-get"
PACKAGE_UPDATE_OPTIONS="update -y -qq"
INSTALL_PACKAGES="autoconf autotools-dev fuse libfuse-dev libcurl4-openssl-dev libxml2-dev locales-all mime-support libtool pkg-config libssl-dev attr wget procps python3-pip"
INSTALL_CPPCHECK_OPTIONS=""
INSTALL_JDK_PACKAGES="openjdk-8-jdk"
elif [ "${CONTAINER_FULLNAME}" = "centos:centos8" ]; then
PACKAGE_MANAGER_BIN="dnf"
PACKAGE_UPDATE_OPTIONS="update -y -qq"
INSTALL_PACKAGES="gcc libstdc++-devel gcc-c++ glibc-langpack-en fuse fuse-devel curl-devel libxml2-devel mailcap git automake make openssl-devel attr diffutils wget python2 python3"
INSTALL_CPPCHECK_OPTIONS="--enablerepo=powertools"
INSTALL_JDK_PACKAGES="java-1.8.0-openjdk"
# [NOTE]
# Add -O2 to prevent the warning '_FORTIFY_SOURCE requires compiling with optimization(-O)'.
#
CONFIGURE_OPTIONS="CXXFLAGS='-O2 -std=c++11 -DS3FS_PTHREAD_ERRORCHECK=1' --prefix=/usr --with-openssl"
elif [ "${CONTAINER_FULLNAME}" = "centos:centos7" ]; then
PACKAGE_MANAGER_BIN="yum"
PACKAGE_UPDATE_OPTIONS="update -y"
INSTALL_PACKAGES="gcc libstdc++-devel gcc-c++ glibc-langpack-en fuse fuse-devel curl-devel libxml2-devel mailcap git automake make openssl-devel attr wget python3 epel-release"
INSTALL_CPPCHECK_OPTIONS="--enablerepo=epel"
INSTALL_JDK_PACKAGES="java-1.8.0-openjdk"
# [NOTE]
# Add -O2 to prevent the warning '_FORTIFY_SOURCE requires compiling with optimization(-O)'.
#
CONFIGURE_OPTIONS="CXXFLAGS='-O2 -std=c++11 -DS3FS_PTHREAD_ERRORCHECK=1' --prefix=/usr --with-openssl"
elif [ "${CONTAINER_FULLNAME}" = "fedora:34" ]; then
PACKAGE_MANAGER_BIN="dnf"
PACKAGE_UPDATE_OPTIONS="update -y -qq"
INSTALL_PACKAGES="gcc libstdc++-devel gcc-c++ glibc-langpack-en fuse fuse-devel curl-devel libxml2-devel mailcap git automake make openssl-devel wget attr diffutils python2 procps python3-pip"
INSTALL_CPPCHECK_OPTIONS=""
INSTALL_JDK_PACKAGES="java-1.8.0-openjdk"
elif [ "${CONTAINER_FULLNAME}" = "opensuse/leap:15" ]; then
PACKAGE_MANAGER_BIN="zypper"
PACKAGE_UPDATE_OPTIONS="refresh"
INSTALL_PACKAGES="automake curl-devel fuse fuse-devel gcc-c++ libxml2-devel make openssl-devel python3-pip wget attr"
INSTALL_CPPCHECK_OPTIONS=""
INSTALL_JDK_PACKAGES="java-1_8_0-openjdk"
else
exit 1
fi
#-----------------------------------------------------------
# Install
#-----------------------------------------------------------
#
# Update packages (ex. apt-get update -y -qq)
#
echo "${PRGNAME} [INFO] Updates."
${PACKAGE_MANAGER_BIN} ${PACKAGE_UPDATE_OPTIONS}
#
# Install pacakages ( with cppcheck )
#
echo "${PRGNAME} [INFO] Install packages."
${PACKAGE_MANAGER_BIN} install -y ${INSTALL_PACKAGES}
echo "${PRGNAME} [INFO] Install cppcheck package."
${PACKAGE_MANAGER_BIN} ${INSTALL_CPPCHECK_OPTIONS} install -y cppcheck
#
# Install JDK 1.8
#
# [NOTE]
# Now, the previous Java LTS version 8 is not available in the official Debian Buster repositories.
# It'll enable the AdoptOpenJDK repository, which provides prebuilt OpenJDK packages.
#
echo "${PRGNAME} [INFO] Install JDK 1.8 package."
if [ "${CONTAINER_FULLNAME}" != "debian:buster" ]; then
${PACKAGE_MANAGER_BIN} install -y ${INSTALL_JDK_PACKAGES}
else
# [NOTE]
# Debian Buster is special case for installing JDK.
#
${PACKAGE_MANAGER_BIN} install -y apt-transport-https ca-certificates dirmngr gnupg software-properties-common
wget -qO - https://adoptopenjdk.jfrog.io/adoptopenjdk/api/gpg/key/public | apt-key add -
add-apt-repository --yes https://adoptopenjdk.jfrog.io/adoptopenjdk/deb/
${PACKAGE_MANAGER_BIN} ${PACKAGE_UPDATE_OPTIONS}
${PACKAGE_MANAGER_BIN} install -y ${INSTALL_JDK_PACKAGES}
fi
java -version
#
# Install awscli
#
echo "${PRGNAME} [INFO] Install awscli package."
${PIP_BIN} install ${PIP_OPTIONS} ${INSTALL_AWSCLI_PACKAGES}
${PIP_BIN} install ${PIP_OPTIONS} rsa
#-----------------------------------------------------------
# Set environment for configure
#-----------------------------------------------------------
echo "${PRGNAME} [INFO] Set environment for configure options"
export CONFIGURE_OPTIONS
echo "${PRGNAME} [INFO] Finish Linux helper for installing packages."
exit 0
#
# 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
#

88
.gitignore vendored
View File

@ -1,21 +1,89 @@
#
# s3fs - FUSE-based file system backed by Amazon S3
#
# Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
#
# 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.
#
#
# Compiled Object files
#
*.slo
*.lo
*.o
Makefile
Makefile.in
*.Po
*.Plo
#
# autotools/automake
#
aclocal.m4
autom4te.cache/
autom4te.cache
autoscan.log
config.guess
config.h
config.h.in
config.h.in~
config.log
config.status
config.sub
configure
configure.scan
depcomp
doc/Makefile
doc/Makefile.in
install-sh
libtool
ltmain.sh
m4
m4/*
missing
src/.deps/
src/Makefile
src/Makefile.in
stamp-h1
Makefile
Makefile.in
test-driver
compile
missing
#
# object directories
#
.deps
.libs
*/.deps
*/.deps/*
*/.libs
*/.libs/*
#
# each directories
#
*.log
*.trs
default_commit_hash
src/s3fs
test/Makefile
test/Makefile.in
src/test_curl_util
src/test_page_list
src/test_string_util
test/chaos-http-proxy-*
test/s3proxy-*
#
# Local variables:
# tab-width: 4
# c-basic-offset: 4
# End:
# vim600: noet sw=4 ts=4 fdm=marker
# vim<600: noet sw=4 ts=4
#

7
.mailmap Normal file
View File

@ -0,0 +1,7 @@
Adrian Petrescu <apetresc@df820570-a93a-0410-bd06-b72b767a4274>
Adrian Petrescu <apetresc@gmail.com@df820570-a93a-0410-bd06-b72b767a4274>
Ben Lemasurier <ben.lemasurier@gmail.com@df820570-a93a-0410-bd06-b72b767a4274>
Dan Moore <mooredan@suncup.net@df820570-a93a-0410-bd06-b72b767a4274>
Randy Rizun <rrizun@df820570-a93a-0410-bd06-b72b767a4274>
Randy Rizun <rrizun@rrizun-ThinkPad-T530.(none)>
Takeshi Nakatani <ggtakec@gmail.com@df820570-a93a-0410-bd06-b72b767a4274>

View File

@ -17,3 +17,7 @@ Bugfixes, performance and other improvements.
5. Takeshi Nakatani <ggtakec@gmail.com>
Bugfixes, performance and other improvements.
6. Andrew Gaul <gaul@gaul.org>
Bugfixes, performance and other improvements.

34
COMPILATION.md Normal file
View File

@ -0,0 +1,34 @@
# Compilation from source code
These are generic instructions should work on almost any GNU/Linux, macOS, BSD, or similar.
If you want specific instructions for some distributions, check the [wiki](https://github.com/s3fs-fuse/s3fs-fuse/wiki/Installation-Notes).
Keep in mind using the pre-built packages when available.
1. Ensure your system satisfies build and runtime dependencies for:
* fuse >= 2.8.4
* automake
* gcc-c++
* make
* libcurl
* libxml2
* openssl
* mime.types (the package providing depends on the OS)
* s3fs tries to detect `/etc/mime.types` as default regardless of the OS
* Else s3fs tries to detect `/etc/apache2/mime.types` if OS is macOS
* s3fs exits with an error if these files are not exist
* Alternatively, you can set mime.types file path with `mime` option without detecting these default files
* pkg-config (or your OS equivalent)
2. Then compile from master via the following commands:
```
git clone https://github.com/s3fs-fuse/s3fs-fuse.git
cd s3fs-fuse
./autogen.sh
./configure
make
sudo make install
```

537
ChangeLog
View File

@ -1,6 +1,479 @@
ChangeLog for S3FS
ChangeLog for S3FS
------------------
Version 1.90 -- 07 Aug, 2021 (major changes only)
#1599 - Don't ignore nomultipart when storage is low
#1600 - #1602 - #1604 - #1617 - #1619 - #1620 - #1623 - #1624 - Fix POSIX compatibility issues found by pjdfstest
#1630 - Fail CheckBucket when S3 returns PermanentRedirect
#1640 - #1655 - Do not create zero-byte object when creating file
#1648 - Allow arbitrary size AWS secret keys
#1668 - #1678 - Fix race conditions
#1696 - Set explicit Content-Length: 0 when initiating MPU
#1681 - Set CURLOPT_UNRESTRICTED_AUTH when authenticating
#1723 - Add jitter to avoid thundering herd
#1728 - Loosen CheckBucket to check only the bucket
#1729 - Add support for AWS-style environment variables
Version 1.89 -- 22 Feb, 2021 (major changes only)
#1520 - #1525 - #1534 - #1549 - Propagate S3 errors to errno more accurately
#1546 - #1559 - Allow writing > 5 GB single-part objects supported by some non-AWS S3
#1553 - #1555 - Allow configuration of multipart copy size and limit to 5 GB
#1562 - Allow configuration of multipart upload threshold and reduce default to 25 MB
#1565 - Set default stat timeout to 900 seconds correctly
#1579 - #1582 - Fix data corruption while updating metadata with use_cache
Version 1.88 -- 4 Jan, 2021 (major changes only)
#1349 - Fixed a bug about move file over limit of ensure space
#1363 - #1366 - #1439 - Fix multiple race conditions
#1365 - Dynamically determine whether lseek extended options are supported
#1374 - Add support for deep archive storage class
#1385 - Plug FdEntity leaks
#1388 - Fix use_session_token option parsing
#1392 - Allow 32-bit platforms to upload single-part objects > 2 GB
#1404 - Fix dead lock in disk insufficient and optimize code
#1408 - Ensure environment variable is set when using ECS
#1413 - not call put headers if not exist pending meta
#1425 - Do not send SSE headers during bucket creation
#1432 - Add sigv4 only option
#1437 - Add atime and correct atime/mtime/ctime operations
#1447 - Fixed a bug that symlink could not be read after restarting s3fs
#1448 - #1467 - Periodically flush written data to reduce temporary local storage
#1449 - Added logfile option for non-syslog logging
#1462 - Add AWS IMDSv2 support
#1502 - #1503 - #1505 - Fix multiple issues when retrying requests
Version 1.87 -- 10 Aug, 2020 (major changes only)
#1244 - use correct content-type when complete multipart upload
#1265 - Fixed a bug of stats cache compression
#1271 - Fixed the truncation bug of stat file for cache file
#1274 - Improved strictness of cache file stats(file)
#1277 - Fixed insufficient upload size for mix multipart upload
#1282 - Warn about missing MIME types instead of exiting
#1285 - Not abort process by exception threw from s3fs_strtoofft
#1286 - Support Google Cloud Storage headers
#1295 - Added a parameter to output body to curldbg option
#1302 - Fix renames of open files with nocopyapi option
#1303 - Relink cache stats file atomically via rename
#1305 - Ignore case when comparing ETags
#1306 - Retry with exponential backoff during 500 error
#1312 - Fixed a bug about serializing from cache file
#1313 - Fixed about ParallelMixMultipartUpload
#1316 - Add support for glacier storage class
#1319 - Fixed upload error about mixuploading sparse file and truncating file
#1334 - Added SIGUSR1 option for cache file integrity test
#1341 - Change default stat_cache_expire
Version 1.86 -- 04 Feb, 2020 (major changes only)
#965 - enable various optimizations when using modern curl
#1002 - allow SSE-C keys to have NUL bytes
#1008 - add session token support
#1039 - allow large files on 32-bit systems like Raspberry Pi
#1049 - fix data corruption when external modification changes a cached object
#1063 - fix data corruption when opening a second fd to an unflushed file
#1066 - fix clock skew errors when writing large files
#1081 - allow concurrent metadata queries during data operations
#1098 - use server-side copy for partially modified files
#1107 - #1108 - fix multiple concurrency issues
#1199 - add requester_pays support
#1209 - add symlink cache
#1224 - add intelligent_ia storage tier
Version 1.85 -- 11 Mar, 2019
#804 - add Backblaze B2
#812 - Fix typo s/mutliple/multiple/
#819 - #691: Made instructions for creating password file more obvious.
#820 - Enable big writes if capable
#826 - For RPM distributions fuse-libs is enough
#831 - Add support for storage class ONEZONE_IA.
#832 - Simplify hex conversion
#833 - New installation instructions for Fedora >= 27 and CentOS7
#834 - Improve template for issues
#835 - Make the compilation instructions generic
#840 - Replace all mentions to MacOS X to macOS
#849 - Correct typo
#851 - Correctly compare list_object_max_keys
#852 - Allow credentials from ${HOME}/.aws/credentials
#853 - Replace ~ with ${HOME} in examples
#855 - Include StackOverflow in FAQs
#856 - Add icon for s3fs
#859 - Upload S3 parts without batching
#861 - Add 'profile' option to command line help.
#865 - fix multihead warning check
#866 - Multi-arch support for ppc64le
#870 - Correct typos in command-line parsing
#874 - Address cppcheck 1.86 errors
#877 - Check arguments and environment before .aws/creds
#882 - [curl] Assume long encryption keys are base64 encoded
#885 - Update s3fs_util.cpp for correspondence of Nextcloud contype
#888 - Add Server Fault to FAQs
#892 - Repair xattr tests
#893 - Store and retrieve file change time
#894 - Default uid/gid/mode when object lacks permissions
#895 - Emit more friendly error for buckets with dots
#898 - Flush file before renaming
#899 - Tighten up HTTP response code check
#900 - Plug memory leak
#901 - Plug memory leaks
#902 - Avoid pass-by-value when not necessary
#903 - Prefer find(char) over find(const char *)
#904 - Remove unnecessary calls to std::string::c_str
#905 - Fix comparison in s3fs_strtoofft
#906 - Prefer HTTPS links where possible
#908 - Added an error message when HTTP 301 status
#909 - Ignore after period character of floating point in x-amz-meta-mtime
#910 - Added a missing extension to .gitignore, and formatted dot files
#911 - Added detail error message when HTTP 301/307 status
#912 - Automatic region change made possible other than us-east-1(default)
#913 - Prefer abort over assert(false)
#914 - Issue readdir HEAD requests without batching
#917 - Reference better-known AWS CLI for compatibility
#918 - Load tail range during overwrite
#919 - Add test for mv non-empty directory
#920 - Remove unnecessary string copies
#921 - Remove redundant string initializations
#923 - Reverted automatic region change and changed messages
#924 - Prefer empty over size checks
#925 - Remove redundant null checks before delete
#926 - Accept paths with : in them
#930 - Correct enable_content_md5 docs
#931 - Correct sigv2 typo
#932 - Prefer AutoLock for synchronization
#933 - Remove mirror path when deleting cache
#934 - Checked and corrected all typo
#937 - Disable malloc_trim
#938 - Remove unneeded void parameter
#939 - Prefer specific [io]stringstream where possible
#940 - Copy parts in parallel
#942 - Ensure s3fs compiles with C++03
#943 - Return not supported when hard linking
#944 - Repair utility mode
#946 - Simplify async request completion code
#948 - Add logging for too many parts
#949 - Implement exponential backoff for 503
#950 - Added S3FS_MALLOC_TRIM build switch
#951 - Added a non-interactive option to utility mode
#952 - Automatically abort failed multipart requests
#953 - Update s3ql link
#954 - Clear containers instead of individual erases
#955 - Address miscellaneous clang-tidy warnings
#957 - Upgrade to S3Proxy 1.6.1
#958 - Document lack of inotify support
#959 - Fixed code for latest cppcheck error on OSX
#960 - Wtf8
#961 - Work around cppcheck warnings
#965 - Improvement of curl session pool for multipart
#967 - Increase FdEntity reference count when returning
#969 - Fix lazy typo
#970 - Remove from file from stat cache during rename
#972 - Add instructions for Amazon Linux
#974 - Changed the description order of man page options
#975 - Fixed ref-count when error occurred.
#977 - Make macOS instructions consistent with others
Version 1.84 -- Jul 8, 2018
#704 - Update README.md with details about .passwd-s3fs
#710 - add disk space reservation
#712 - Added Cygwin build options
#714 - reduce lock contention on file open
#724 - don't fail multirequest on single thread error
#726 - add an instance_name option for logging
#727 - Fixed Travis CI error about cppcheck - #713
#729 - FreeBSD build fixes
#733 - More useful error message for dupe entries in passwd file
#739 - cleanup curl handle state on retries
#745 - don't fail mkdir when directory exists
#753 - fix xpath selector in bucket listing
#754 - Validate the URL format for http/https
#755 - Added reset curl handle when returning to handle pool
#756 - Optimize defaults
#761 - Simplify installation for Ubuntu 16.04
#762 - Upgrade to S3Proxy 1.6.0
#763 - cleanup curl handles before curl share
#764 - Remove false multihead warnings
#765 - Add Debian installation instructions
#766 - Remove s3fs-python
#768 - Fixed memory leak
#769 - Revert "enable FUSE read_sync by default"
#774 - Option for IAM authentication endpoint
#780 - gnutls_auth: initialize libgcrypt
#781 - Fixed an error by cppcheck on OSX
#786 - Log messages for 5xx and 4xx HTTP response code
#789 - Instructions for SUSE and openSUSE prebuilt packages
#793 - Added list_object_max_keys option based on #783 PR
Version 1.83 -- Dec 17, 2017
#606 - Add Homebrew instructions
#608 - Fix chown_nocopy losing existing uid/gid if unspecified
#609 - Group permission checks sometimes fail with large number of groups
#611 - Fixed clock_gettime build failure on macOS 10.12 Sierra - #600
#621 - Upgrade to S3Proxy 1.5.3
#627 - Update README.md
#630 - Added travis test on osx for #601
#631 - Merged macosx branch into master branch #601
#636 - Fix intermittent upload failures on macOS
#637 - Add blurb about non-Amazon S3 implementations
#638 - Minor fixes to README
#639 - Update Homebrew instructions
#642 - Fixed potential atomic violation in S3fsCurl::AddUserAgent - #633
#644 - Fixed with unnecessary equal in POST uploads url argument - #643
#645 - Configure S3Proxy for SSL
#646 - Simplify S3Proxy PID handling
#652 - Fix s3fs_init message
#659 - Do not fail updating directory when removing old-style object(ref #658)
#660 - Refixed s3fs_init message(ref #652)
#663 - Lock FdEntity when mutating orgmeta
#664 - auth headers insertion refactoring
#668 - Changed .travis.yml for fixing not found gpg2 on osx
#669 - add IBM IAM authentication support
#670 - Fixed a bug in S3fsCurl::LocateBundle
#671 - Add support for ECS metadata endpoint
#675 - Reduce use of preprocessor
#676 - Move str definition from header to implementation
#677 - Add s3proxy to .gitignore
#679 - README.md Addition
#681 - Changed functions about reading passwd file
#684 - Correct signedness warning
#686 - remove use of jsoncpp
#688 - Improved use of temporary files - #678
#690 - Added option ecs description to man page
#692 - Updated template md files for issue and pr
#695 - fix condition for parallel download
#697 - Fixing race condition in FdEntity::GetStats
#699 - Fix dbglevel usage
Version 1.82 -- May 13, 2017
#597 - Not fallback to HTTP - #596
#598 - Updated ChangeLog and configure.ac for release 1.82
Version 1.81 -- May 13, 2017
#426 - Updated to correct ChangeLog
#431 - fix typo s/controll/control/
#432 - Include location constraint when creating bucket
#433 - Correct search and replace typo
#440 - Handled all curl error without exiting process - #437
#443 - Fix for leaks during stat cache entry expiry / truncation (#340)
#444 - Add mirror file logic for removing cache file
#447 - added fuse package for mounting via /etc/fstab, fixes #417
#449 - Accept mount options compatible with mtab
#451 - Correct path in README
#454 - Changed for accepting mount options compatible with mtab - #449
#466 - Fixed a bug about could not copy file mode from org file
#471 - Added use_xattr option for #467 and #460
#477 - OS-specific correspondence of the extended attribute header
#483 - Trim symbolic link original path in file
#487 - Split header debugging onto multiple lines for easier reading
#488 - Fixed searching Content-Length without case sensitive - #480
#489 - Changed headers_t map using nocase compare function - #488
#494 - Fix typo s/destroied/destroyed/
#495 - Fix invalid V4 signature on multipart copy requests
#498 - Upgrade to S3Proxy 1.5.1
#502 - Fixed issue#435 branch codes for remaining bugs(2)
#503 - Add missing call to mtime test
#504 - Use describe helper function
#505 - Correct typos
#509 - Use server-provided ETag during complete upload
#511 - Fixed a bug about uploading NULL to some part of the file contents
#512 - Changed clock_gettime func to s3fs_clock_gettime for homebrew - #468
#513 - Added issue and PR templates.
#517 - Update s3fs.1 - removed duplicated word
#520 - Added links for eventual consistency in README.md - #515
#539 - Upgrade to S3Proxy 1.5.2
#540 - Address cppcheck 1.77 warnings
#545 - Changed base cached time of stat_cache_expire option - #523
#546 - Fixed double initialization of SSL library at foreground
#550 - Add umount instruction for unprivileged user
#551 - Updated stat_cache_expire option description - #545
#552 - switch S3fsMultiCurl to use foreground threads
#553 - add TLS cipher suites customization
#554 - cleanup cache directory when running out of disk space
#555 - don't sign empty headers (as they are discarded
#556 - fix multipart upload handling without cache
#557 - Added check_cache_dir_exist option(refixed #347) - #538
#558 - Fixed a bug in logic about truncating stat cache
#560 - Fixed about multipart uploading at no free space related to #509
#567 - Do not send ACL unless overridden
#576 - Added option for complementing lack of stat mode
#578 - Refactored the get_object_attribute function
#579 - Added notsup_compat_dir option
#580 - Enhanced bucket/path parameter check
#582 - Check errors returned in 200 OK responses for put header request
#583 - Updated limit object size in s3fs man page
#585 - Fixed failure to upload/copy with SSE_C and SSE_KMS
#587 - Changed copyright year format for debian pkg
#588 - Default transport to HTTPS
#590 - Updated man page for default_acl option - #567
#593 - Backward compatible for changing default transport to HTTPS
#594 - Check bucket at public bucket and add nocopyapi option automatically
#595 - Updated ChangeLog and configure.ac for release 1.81
Version 1.80 -- May 29, 2016
#213 - Parse ETag from copy multipart correctly
#215 - Fix mem leak in openssl_auth.cpp:s3fs_sha256hexsum
#217 - Override install, so that the make install does not install rename_before_close under /test
#219 - Address Coverity errors
#220 - Test removing a non-empty directory
#221 - Compare idiomatically
#222 - Annotate constructors as explicit
#224 - Configure cppcheck
#229 - Convert rename_before_close to a shell script
#231 - Rewrite AutoLock
#232 - Always hold stat_cache_lock when using stat_cache
#233 - Remove IntToStr
#234 - Update README
#235 - Plug leak during complete multipart upload
#237 - Refactor tests into individual functions
#238 - Enable all cppcheck rules
#239 - Update stale Google Code reference in --help
#240 - Enable Content-MD5 during multipart upload part
#243 - Run cppcheck during Travis builds
#245 - Elide duplicate lookups of std::map via iterators
#246 - Unlock during early return in TruncateCache
#247 - Base64 cleanup
#248 - Enable integration tests for Travis
#249 - Silence wget
#250 - s3fs can print version with short commit hash - #228
#251 - Skip xattr tests if utilities are missing
#252 - This fixes an issue with caching when the creation of a subdirectory …
#253 - Added checking cache dir perms at starting.
#256 - Add no atomic rename to limitations
#257 - Update README.md: Bugfix password file permissions errors
#258 - Update README.md to better explain mount upon boot
#260 - Wrap help text at 80 characters
#261 - Correct help timeouts
#263 - Allow integration testing against Amazon S3
#265 - Fix integration tests
#266 - Cleanup from PR #265
#267 - Added the _netdev option to the fstab example.
#268 - Use 127.0.0.1 not localhost in s3proxy wait loop
#271 - Add support for standard_ia storage class
#274 - Modified man page for storage_class option(#271)
#275 - Changed and cleaned the logic for debug message.
#278 - Supported for SSE KMS(#270)
#280 - Supported a object which is larger than free disk space
#285 - Add test for symlink
#288 - Fixed a bug about head request(copy) for SSE - issue#286
#289 - Print source file in log messages
#291 - File opened with O_TRUNC is not flushed - Issue #290
#293 - Fix a small spelling issue.
#295 - File opened with O_TRUNC is not flushed - changed #291
#300 - Update integration-test-main.sh
#302 - Fix syslog level used by S3FS_PRN_EXIT()
#304 - Fixed a bug about mtime - #299
#306 - Fix read concurrency to work in parallel count
#307 - Fix pthread portability problem
#308 - Changed ensure free disk space as additional change for #306
#309 - Check pthread portability in configure as additional change for #307
#310 - Update integration-test-main.sh as additional change for #300
#311 - Change error log to debug log in s3fs_read()
#313 - fix gitignore
#319 - Clean up mount point on errors in s3fs_init()
#321 - delete stat cache entry in s3fs_fsync so st_size is refreshed - #320
#323 - Add goofys to references
#328 - Fix v4 signature with use_path_request_style
#329 - Correct multiple issues with GET and v4 signing
#330 - Pass by const reference where possible
#331 - Address various clang warnings
#334 - Bucket host should include port and not path
#336 - update README.md for fstab
#338 - Fixed a bug about IAMCRED type could not be retried.
#339 - Updated README.md for fstab example.
#341 - Fix the memory leak issue in fdcache.
#346 - Fix empty directory check against AWS S3
#348 - Integration test summary, continue on error
#350 - Changed cache out logic for stat - #340
#351 - Check cache directory path and attributes - #347
#352 - Remove stat file cache dir if specified del_cache - #337
#354 - Supported regex type for additional header format - #343
#355 - Fixed codes about clock_gettime for osx
#356 - Fixed codes about clock_gettime for osx(2)
#357 - Fixed codes about clock_gettime for osx(3)
#359 - Remove optional parameter from Content-Type header - #358
#360 - Fix clock_gettime autotools detection on Linux
#364 - Checked content-type by no case-sensitivity - #363
#371 - Always set stats cache for opened file
#372 - Fixed a bug about etag comparison in stats cache, etc.
#376 - Test for writing after an lseek past end of file
#379 - Fixed a bug about writing sparsed file - #375
#385 - fix typo in curl.cpp: s/returing/returning/
#391 - Update s3fs.1
#394 - Revert "Fixed a bug about writing sparsed file - #375"
#395 - Fixed writing sparsed file - #375,#379,#394
#397 - Supported User-Agent header - #383
#403 - Fix a bug of truncating empty file
#404 - Add curl handler pool to reuse connections
#409 - Fixed 'load_sse_c' option not working - #388
#410 - Allow duplicate key in ahbe_conf - #386
#411 - loading IAM role name automatically(iam_role option) - #387
#415 - Fixed a bug about stat_cache_expire - #382
#420 - Skip early credential checks when iam_role=auto
#422 - Fixes for iam_role=auto
#424 - Added travis CI badge in README.md
#425 - Updated ChangeLog and configure.ac for release 1.80
Version 1.79 -- Jul 19, 2015
issue #60 - Emit user-friendly log messages on failed CheckBucket requests
issue #62 - Remove stray chars from source files
issue #63 - Fix spelling errors
issue #68 - FreeBSD issue
issue #69 - Address clang always true warnings
issue #73 - Small gitignore fixes
issue #74 - url: handle scheme omission
issue #83 - Changed option processing to use strtol() to get a umask
issue #93 - Add simple unit tests for trim functions
issue #100 - CURL handles not properly initialized to use DNS or SSL session caching
issue #101 - Optimized function "bool directory_empty()"
issue #103 - Remove prefix option in s3fs man page - issue#87
issue #104 - fix rename before close
issue #116 - Supported signature version 4
issue #119 - Added new mp_umask option about issue#107, pr#110
issue #124 - Fallback to v2 signatures correctly.
issue #130 - refactor integration tests create/cleanup file
issue #131 - Test ls
issue #132 - Use S3Proxy to run integration tests
issue #134 - Include Content-Type in complete MPU V2 signature
issue #135 - Correct V4 signature for initiate multipart upload
issue #136 - Small fixes to integration tests
issue #137 - Add test for multi-part upload
issue #138 - Fixed bugs, not turn use_cache off and ty to load to end - issue#97
issue #143 - Fixed a bug no use_cache case about fixed #138 - issue#141
issue #144 - Add Travis configuration
issue #146 - add exit handler to cleanup on failures
issue #147 - Use S3Proxy 1.4.0-SNAPSHOT
issue #150 - Fixed a bug not handling fsync - #145
issue #154 - Fixed url-encoding for ampersand etc on sigv4 - Improvement/#149
issue #155 - Fixed a bug: unable to mount bucket subdirectory
issue #156 - Fixed a bug about ssl session sharing with libcurl older 7.23.0 - issue#126
issue #159 - Upgrade to S3Proxy 1.4.0
issue #164 - send the correct Host header when using -o url
issue #165 - Auth v4 refactor
issue #167 - Increased default connecting/reading/writing timeout value
issue #168 - switch to use region specific endpoints to compute correct v4 signature
issue #170 - Reviewed and fixed response codes print in curl.cpp - #157
issue #171 - Support buckets with mixed-case names
issue #173 - Run integration tests via Travis
issue #176 - configure.ac: detect target, if target is darwin (OSX), then #176
issue #177 - Add .mailmap
issue #178 - Update .gitignore
issue #184 - Add usage information for multipart_size
issue #185 - Correct obvious typos in usage and README
issue #190 - Add a no_check_certificate option.
issue #194 - Tilda in a file-name breaks things (EPERM)
issue #198 - Disable integration tests for Travis
issue #199 - Supported extended attributes(retry)
issue #200 - fixed fallback to sigv2 for bucket create and GCS
issue #202 - Specialize {set,get}xattr for OS X
issue #204 - Add integration test for xattr
issue #207 - Fixed a few small spelling issues.
Version 1.78 -- Sep 15, 2014
issue #29 - Possible to create Debian/Ubuntu packages?(googlecode issue 109)
issue 417(googlecode) - Password file with DOS format is not handled properly
issue #41 - Failed making signature
issue #40 - Moving a directory containing more than 1000 files truncates the directory
issue #49 - use_sse is ignored when creating new files
issue #39 - Support for SSE-C
issue #50 - Cannot find pkg-config when configured with any SSL backend except openssl
Version 1.77 -- Apr 19, 2014
issue 405(googlecode) - enable_content_md5 Input/output error
issue #14 - s3fs -u should return 0 if there are no lost multiparts
@ -22,97 +495,97 @@ issue #4 - Fix compilation error on MacOSX with missing const
Version 1.74 -- Nov 24, 2013
This version is initial version on Github, same as on GoogleCodes(s3fs).
https://github.com/s3fs-fuse/s3fs-fuse/releases/tag/v1.74
see more detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.74.tar.gz
see more detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.74.tar.gz
Version 1.73 -- Aug 23, 2013
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.73.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.73.tar.gz
Version 1.72 -- Aug 10, 2013
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.72.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.72.tar.gz
Version 1.71 -- Jun 15, 2013
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.71.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.71.tar.gz
Version 1.70 -- Jun 01, 2013
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.70.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.70.tar.gz
Version 1.69 -- May 15, 2013
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.69.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.69.tar.gz
Version 1.68 -- Apr 30, 2013
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.68.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.68.tar.gz
Version 1.67 -- Apr 13, 2013
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.67.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.67.tar.gz
Version 1.66 -- Apr 06, 2013
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.66.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.66.tar.gz
Version 1.65 -- Mar 30, 2013
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.65.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.65.tar.gz
Version 1.64 -- Mar 23, 2013
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.64.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.64.tar.gz
Version 1.63 -- Feb 24, 2013
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.63.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.63.tar.gz
Version 1.62 -- Jan 27, 2013
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.62.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.62.tar.gz
Version 1.61 -- Aug 30, 2011
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.61.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.61.tar.gz
Version 1.60 -- Aug 29, 2011
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.60.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.60.tar.gz
Version 1.59 -- Jul 28, 2011
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.59.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.59.tar.gz
Version 1.58 -- Jul 19, 2011
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.58.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.58.tar.gz
Version 1.57 -- Jul 07, 2011
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.57.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.57.tar.gz
Version 1.56 -- Jul 07, 2011
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.56.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.56.tar.gz
Version 1.55 -- Jul 02, 2011
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.55.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.55.tar.gz
Version 1.54 -- Jun 25, 2011
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.54.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.54.tar.gz
Version 1.53 -- Jun 22, 2011
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.53.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.53.tar.gz
Version 1.40 -- Feb 11, 2011
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.40.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.40.tar.gz
Version 1.33 -- Dec 30, 2010
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.33.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.33.tar.gz
Version 1.25 -- Dec 16, 2010
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.25.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.25.tar.gz
Version 1.19 -- Dec 2, 2010
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.19.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.19.tar.gz
Version 1.16 -- Nov 22, 2010
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.16.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.16.tar.gz
Version 1.10 -- Nov 6, 2010
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.10.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.10.tar.gz
Version 1.02 -- Oct 29, 2010
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.02.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.02.tar.gz
Version 1.01 -- Oct 28, 2010
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.01.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.01.tar.gz
Version 1.0 -- Oct 24, 2010
see detail on googlecodes: http://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.0.tar.gz
see detail on googlecodes: https://code.google.com/p/s3fs/downloads/detail?name=s3fs-1.0.tar.gz
------
Version 1.1 -- Mon Oct 18 2010

View File

@ -124,7 +124,7 @@ architecture at a time in the source code directory. After you have
installed the package for one architecture, use `make distclean' before
reconfiguring for another architecture.
On MacOS X 10.5 and later systems, you can create libraries and
On macOS 10.5 and later systems, you can create libraries and
executables that work on multiple system types--known as "fat" or
"universal" binaries--by specifying multiple `-arch' options to the
compiler but only a single `-arch' option to the preprocessor. Like

View File

@ -19,7 +19,7 @@
######################################################################
SUBDIRS=src test doc
EXTRA_DIST=doc
EXTRA_DIST=doc default_commit_hash
dist-hook:
rm -rf `find $(distdir)/doc -type d -name .svn`
@ -28,3 +28,26 @@ dist-hook:
release : dist ../utils/release.sh
../utils/release.sh $(DIST_ARCHIVES)
cppcheck:
cppcheck --quiet --error-exitcode=1 \
--inline-suppr \
--std=c++03 \
--xml \
-D HAVE_ATTR_XATTR_H \
-D HAVE_SYS_EXTATTR_H \
-D HAVE_MALLOC_TRIM \
-U CURLE_PEER_FAILED_VERIFICATION \
-U ENOATTR \
--enable=warning,style,information,missingInclude \
--suppress=missingIncludeSystem \
--suppress=unmatchedSuppression \
src/ test/
#
# Local variables:
# tab-width: 4
# c-basic-offset: 4
# End:
# vim600: expandtab sw=4 ts= fdm=marker
# vim<600: expandtab sw=4 ts=4
#

0
NEWS
View File

67
README
View File

@ -1,67 +0,0 @@
THIS README CONTAINS OUTDATED INFORMATION - please refer to the wiki or --help
S3FS-Fuse
S3FS is FUSE (File System in User Space) based solution to mount/unmount an Amazon S3 storage buckets and use system commands with S3 just like it was another Hard Disk.
In order to compile s3fs, You'll need the following requirements:
* Kernel-devel packages (or kernel source) installed that is the SAME version of your running kernel
* LibXML2-devel packages
* CURL-devel packages (or compile curl from sources at: curl.haxx.se/ use 7.15.X)
* GCC, GCC-C++
* pkgconfig
* FUSE (>= 2.8.4)
* FUSE Kernel module installed and running (RHEL 4.x/CentOS 4.x users - read below)
* OpenSSL-devel (0.9.8)
GnuTLS(gcrypt and nettle)
NSS
* Git
If you're using YUM or APT to install those packages, then it might require additional packaging, allow it to be installed.
Downloading & Compiling:
------------------------
In order to download s3fs, download from following url:
https://github.com/s3fs-fuse/s3fs-fuse/archive/master.zip
Or clone the following command:
git clone git://github.com/s3fs-fuse/s3fs-fuse.git
Go inside the directory that has been created (s3fs-fuse) and run: ./autogen.sh
This will generate a number of scripts in the project directory, including a configure script which you should run with: ./configure
If configure succeeded, you can now run: make. If it didn't, make sure you meet the dependencies above.
This should compile the code. If everything goes OK, you'll be greated with "ok!" at the end and you'll have a binary file called "s3fs"
in the src/ directory.
As root (you can use su, su -, sudo) do: "make install" -this will copy the "s3fs" binary to /usr/local/bin.
Congratulations. S3fs is now compiled and installed.
Usage:
------
In order to use s3fs, make sure you have the Access Key and the Secret Key handy. (refer to the wiki)
First, create a directory where to mount the S3 bucket you want to use.
Example (as root): mkdir -p /mnt/s3
Then run: s3fs mybucket[:path] /mnt/s3
This will mount your bucket to /mnt/s3. You can do a simple "ls -l /mnt/s3" to see the content of your bucket.
If you want to allow other people access the same bucket in the same machine, you can add "-o allow_other" to read/write/delete content of the bucket.
You can add a fixed mount point in /etc/fstab, here's an example:
s3fs#mybucket /mnt/s3 fuse allow_other 0 0
This will mount upon reboot (or by launching: mount -a) your bucket on your machine.
If that does not work, probably you should specify with "_netdev" option in fstab.
All other options can be read at: https://github.com/s3fs-fuse/s3fs-fuse/wiki/Fuse-Over-Amazon
Known Issues:
-------------
s3fs should be working fine with S3 storage. However, There are couple of limitations:
* Currently s3fs could hang the CPU if you have lots of time-outs. This is *NOT* a fault of s3fs but rather libcurl. This happends when you try to copy thousands of files in 1 session, it doesn't happend when you upload hundreds of files or less.
* CentOS 4.x/RHEL 4.x users - if you use the kernel that shipped with your distribution and didn't upgrade to the latest kernel RedHat/CentOS gives, you might have a problem loading the "fuse" kernel. Please upgrade to the latest kernel (2.6.16 or above) and make sure "fuse" kernel module is compiled and loadable since FUSE requires this kernel module and s3fs requires it as well.
* Moving/renaming/erasing files takes time since the whole file needs to be accessed first. A workaround could be to use s3fs's cache support with the use_cache option.

172
README.md Normal file
View File

@ -0,0 +1,172 @@
# s3fs
s3fs allows Linux and macOS to mount an S3 bucket via FUSE.
s3fs preserves the native object format for files, allowing use of other
tools like [AWS CLI](https://github.com/aws/aws-cli).
[![s3fs-fuse CI](https://github.com/s3fs-fuse/s3fs-fuse/workflows/s3fs-fuse%20CI/badge.svg)](https://github.com/s3fs-fuse/s3fs-fuse/actions)
[![Twitter Follow](https://img.shields.io/twitter/follow/s3fsfuse.svg?style=social&label=Follow)](https://twitter.com/s3fsfuse)
## Features
* large subset of POSIX including reading/writing files, directories, symlinks, mode, uid/gid, and extended attributes
* compatible with Amazon S3, and other [S3-based object stores](https://github.com/s3fs-fuse/s3fs-fuse/wiki/Non-Amazon-S3)
* allows random writes and appends
* large files via multi-part upload
* renames via server-side copy
* optional server-side encryption
* data integrity via MD5 hashes
* in-memory metadata caching
* local disk data caching
* user-specified regions, including Amazon GovCloud
* authenticate via v2 or v4 signatures
## Installation
Many systems provide pre-built packages:
* Amazon Linux via EPEL:
```
sudo amazon-linux-extras install epel
sudo yum install s3fs-fuse
```
* Arch Linux:
```
sudo pacman -S s3fs-fuse
```
* Debian 9 and Ubuntu 16.04 or newer:
```
sudo apt install s3fs
```
* Fedora 27 or newer:
```
sudo dnf install s3fs-fuse
```
* Gentoo:
```
sudo emerge net-fs/s3fs
```
* RHEL and CentOS 7 or newer via EPEL:
```
sudo yum install epel-release
sudo yum install s3fs-fuse
```
* SUSE 12 and openSUSE 42.1 or newer:
```
sudo zypper install s3fs
```
* macOS via [Homebrew](https://brew.sh/):
```
brew install --cask osxfuse
brew install s3fs
```
Note: Homebrew has deprecated osxfuse and s3fs may not install any more, see
[#1618](https://github.com/s3fs-fuse/s3fs-fuse/issues/1618).
Otherwise consult the [compilation instructions](COMPILATION.md).
## Examples
s3fs supports the standard
[AWS credentials file](https://docs.aws.amazon.com/cli/latest/userguide/cli-config-files.html)
stored in `${HOME}/.aws/credentials`. Alternatively, s3fs supports a custom passwd file.
The default location for the s3fs password file can be created:
* using a `.passwd-s3fs` file in the users home directory (i.e. `${HOME}/.passwd-s3fs`)
* using the system-wide `/etc/passwd-s3fs` file
Enter your credentials in a file `${HOME}/.passwd-s3fs` and set
owner-only permissions:
```
echo ACCESS_KEY_ID:SECRET_ACCESS_KEY > ${HOME}/.passwd-s3fs
chmod 600 ${HOME}/.passwd-s3fs
```
Run s3fs with an existing bucket `mybucket` and directory `/path/to/mountpoint`:
```
s3fs mybucket /path/to/mountpoint -o passwd_file=${HOME}/.passwd-s3fs
```
If you encounter any errors, enable debug output:
```
s3fs mybucket /path/to/mountpoint -o passwd_file=${HOME}/.passwd-s3fs -o dbglevel=info -f -o curldbg
```
You can also mount on boot by entering the following line to `/etc/fstab`:
```
mybucket /path/to/mountpoint fuse.s3fs _netdev,allow_other 0 0
```
If you use s3fs with a non-Amazon S3 implementation, specify the URL and path-style requests:
```
s3fs mybucket /path/to/mountpoint -o passwd_file=${HOME}/.passwd-s3fs -o url=https://url.to.s3/ -o use_path_request_style
```
or(fstab)
```
mybucket /path/to/mountpoint fuse.s3fs _netdev,allow_other,use_path_request_style,url=https://url.to.s3/ 0 0
```
Note: You may also want to create the global credential file first
```
echo ACCESS_KEY_ID:SECRET_ACCESS_KEY > /etc/passwd-s3fs
chmod 600 /etc/passwd-s3fs
```
Note2: You may also need to make sure `netfs` service is start on boot
## Limitations
Generally S3 cannot offer the same performance or semantics as a local file system. More specifically:
* random writes or appends to files require rewriting the entire object, optimized with multi-part upload copy
* metadata operations such as listing directories have poor performance due to network latency
* non-AWS providers may have [eventual consistency](https://en.wikipedia.org/wiki/Eventual_consistency) so reads can temporarily yield stale data (AWS offers read-after-write consistency [since Dec 2020](https://aws.amazon.com/about-aws/whats-new/2020/12/amazon-s3-now-delivers-strong-read-after-write-consistency-automatically-for-all-applications/))
* no atomic renames of files or directories
* no coordination between multiple clients mounting the same bucket
* no hard links
* inotify detects only local modifications, not external ones by other clients or tools
## References
* [goofys](https://github.com/kahing/goofys) - similar to s3fs but has better performance and less POSIX compatibility
* [s3backer](https://github.com/archiecobbs/s3backer) - mount an S3 bucket as a single file
* [S3Proxy](https://github.com/gaul/s3proxy) - combine with s3fs to mount Backblaze B2, EMC Atmos, Microsoft Azure, and OpenStack Swift buckets
* [s3ql](https://github.com/s3ql/s3ql/) - similar to s3fs but uses its own object format
* [YAS3FS](https://github.com/danilop/yas3fs) - similar to s3fs but uses SNS to allow multiple clients to mount a bucket
## Frequently Asked Questions
* [FAQ wiki page](https://github.com/s3fs-fuse/s3fs-fuse/wiki/FAQ)
* [s3fs on Stack Overflow](https://stackoverflow.com/questions/tagged/s3fs)
* [s3fs on Server Fault](https://serverfault.com/questions/tagged/s3fs)
## License
Copyright (C) 2010 Randy Rizun <rrizun@gmail.com>
Licensed under the GNU GPL version 2

View File

@ -19,6 +19,36 @@
#
# See the file ChangeLog for a revision history.
echo "--- Make commit hash file -------"
SHORTHASH="unknown"
type git > /dev/null 2>&1
if [ $? -eq 0 -a -d .git ]; then
RESULT=`git rev-parse --short HEAD`
if [ $? -eq 0 ]; then
SHORTHASH=${RESULT}
fi
fi
echo ${SHORTHASH} > default_commit_hash
echo "--- Finished commit hash file ---"
echo "--- Start autotools -------------"
aclocal \
&& autoheader \
&& automake --add-missing \
&& autoconf
echo "--- Finished autotools ----------"
exit 0
#
# Local variables:
# tab-width: 4
# c-basic-offset: 4
# End:
# vim600: expandtab sw=4 ts= fdm=marker
# vim<600: expandtab sw=4 ts=4
#

View File

@ -20,15 +20,41 @@
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
AC_INIT(s3fs, 1.77)
AC_INIT(s3fs, 1.90)
AC_CONFIG_HEADER([config.h])
AC_CANONICAL_SYSTEM
AM_INIT_AUTOMAKE()
AM_INIT_AUTOMAKE([foreign])
AC_PROG_CXX
AC_PROG_CC
CXXFLAGS="$CXXFLAGS -Wall -D_FILE_OFFSET_BITS=64"
AC_CHECK_HEADERS([sys/xattr.h])
AC_CHECK_HEADERS([attr/xattr.h])
AC_CHECK_HEADERS([sys/extattr.h])
AC_CHECK_FUNCS([fallocate])
CXXFLAGS="$CXXFLAGS -Wall -fno-exceptions -D_FILE_OFFSET_BITS=64 -D_FORTIFY_SOURCE=2"
dnl ----------------------------------------------
dnl For macOS
dnl ----------------------------------------------
case "$target" in
*-cygwin* )
# Do something specific for windows using winfsp
CXXFLAGS="$CXXFLAGS -D_GNU_SOURCE=1"
min_fuse_version=2.8
;;
*-darwin* )
# Do something specific for mac
min_fuse_version=2.7.3
;;
*)
# Default Case
# assume other supported linux system
min_fuse_version=2.8.4
;;
esac
dnl ----------------------------------------------
dnl Choice SSL library
@ -156,13 +182,13 @@ dnl
dnl For PKG_CONFIG before checking nss/gnutls.
dnl this is redundant checking, but we need checking before following.
dnl
PKG_CHECK_MODULES([common_lib_checking], [fuse >= 2.8.4 libcurl >= 7.0 libxml-2.0 >= 2.6])
PKG_CHECK_MODULES([common_lib_checking], [fuse >= ${min_fuse_version} libcurl >= 7.0 libxml-2.0 >= 2.6 ])
AC_MSG_CHECKING([compile s3fs with])
case "${auth_lib}" in
openssl)
AC_MSG_RESULT(OpenSSL)
PKG_CHECK_MODULES([DEPS], [fuse >= 2.8.4 libcurl >= 7.0 libxml-2.0 >= 2.6 libcrypto >= 0.9])
PKG_CHECK_MODULES([DEPS], [fuse >= ${min_fuse_version} libcurl >= 7.0 libxml-2.0 >= 2.6 libcrypto >= 0.9 ])
;;
gnutls)
AC_MSG_RESULT(GnuTLS-gcrypt)
@ -171,7 +197,7 @@ gnutls)
AS_IF([test "$gnutls_nettle" = ""], [AC_CHECK_LIB(gcrypt, gcry_control, [gnutls_nettle=0])])
AS_IF([test $gnutls_nettle = 0],
[
PKG_CHECK_MODULES([DEPS], [fuse >= 2.8.4 libcurl >= 7.0 libxml-2.0 >= 2.6 gnutls >= 2.12.0 ])
PKG_CHECK_MODULES([DEPS], [fuse >= ${min_fuse_version} libcurl >= 7.0 libxml-2.0 >= 2.6 gnutls >= 2.12.0 ])
LIBS="-lgnutls -lgcrypt $LIBS"
AC_MSG_CHECKING([gnutls is build with])
AC_MSG_RESULT(gcrypt)
@ -185,7 +211,7 @@ nettle)
AS_IF([test "$gnutls_nettle" = ""], [AC_CHECK_LIB(nettle, nettle_MD5Init, [gnutls_nettle=1])])
AS_IF([test $gnutls_nettle = 1],
[
PKG_CHECK_MODULES([DEPS], [fuse >= 2.8.4 libcurl >= 7.0 libxml-2.0 >= 2.6 nettle >= 2.7.1 ])
PKG_CHECK_MODULES([DEPS], [fuse >= ${min_fuse_version} libcurl >= 7.0 libxml-2.0 >= 2.6 nettle >= 2.7.1 ])
LIBS="-lgnutls -lnettle $LIBS"
AC_MSG_CHECKING([gnutls is build with])
AC_MSG_RESULT(nettle)
@ -194,7 +220,7 @@ nettle)
;;
nss)
AC_MSG_RESULT(NSS)
PKG_CHECK_MODULES([DEPS], [fuse >= 2.8.4 libcurl >= 7.0 libxml-2.0 >= 2.6 nss >= 3.15.0 ])
PKG_CHECK_MODULES([DEPS], [fuse >= ${min_fuse_version} libcurl >= 7.0 libxml-2.0 >= 2.6 nss >= 3.15.0 ])
;;
*)
AC_MSG_ERROR([unknown ssl library type.])
@ -207,12 +233,120 @@ AM_CONDITIONAL([USE_GNUTLS_NETTLE], [test "$auth_lib" = nettle])
AM_CONDITIONAL([USE_SSL_NSS], [test "$auth_lib" = nss])
dnl ----------------------------------------------
dnl end of ssl library
dnl check functions
dnl ----------------------------------------------
dnl malloc_trim function
AC_CHECK_FUNCS(malloc_trim, , )
AC_CHECK_FUNCS([malloc_trim])
dnl clock_gettime function(macos)
AC_SEARCH_LIBS([clock_gettime],[rt posix4])
AC_CHECK_FUNCS([clock_gettime])
dnl ----------------------------------------------
dnl check symbols/macros/enums
dnl ----------------------------------------------
dnl PTHREAD_MUTEX_RECURSIVE
AC_MSG_CHECKING([pthread mutex recursive])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[#include <pthread.h>]],
[[int i = PTHREAD_MUTEX_RECURSIVE;]])
],
[AC_DEFINE(S3FS_MUTEX_RECURSIVE, PTHREAD_MUTEX_RECURSIVE, [Define if you have PTHREAD_MUTEX_RECURSIVE])
AC_MSG_RESULT(PTHREAD_MUTEX_RECURSIVE)
],
[AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[#include <pthread.h>]],
[[int i = PTHREAD_MUTEX_RECURSIVE_NP;]])
],
[AC_DEFINE(S3FS_MUTEX_RECURSIVE, PTHREAD_MUTEX_RECURSIVE_NP, [Define if you have PTHREAD_MUTEX_RECURSIVE_NP])
AC_MSG_RESULT(PTHREAD_MUTEX_RECURSIVE_NP)
],
[AC_MSG_ERROR([do not have PTHREAD_MUTEX_RECURSIVE symbol])])
]
)
dnl ----------------------------------------------
dnl check CURLoption
dnl ----------------------------------------------
dnl CURLOPT_TCP_KEEPALIVE (is supported by 7.25.0 and later)
AC_MSG_CHECKING([checking CURLOPT_TCP_KEEPALIVE])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[#include <curl/curl.h>]],
[[CURLoption opt = CURLOPT_TCP_KEEPALIVE;]])
],
[AC_DEFINE(HAVE_CURLOPT_TCP_KEEPALIVE, 1, [Define to 1 if libcurl has CURLOPT_TCP_KEEPALIVE CURLoption])
AC_MSG_RESULT(yes)
],
[AC_DEFINE(HAVE_CURLOPT_TCP_KEEPALIVE, 0, [Define to 1 if libcurl has CURLOPT_TCP_KEEPALIVE CURLoption])
AC_MSG_RESULT(no)
]
)
dnl CURLOPT_SSL_ENABLE_ALPN (is supported by 7.36.0 and later)
AC_MSG_CHECKING([checking CURLOPT_SSL_ENABLE_ALPN])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[#include <curl/curl.h>]],
[[CURLoption opt = CURLOPT_SSL_ENABLE_ALPN;]])
],
[AC_DEFINE(HAVE_CURLOPT_SSL_ENABLE_ALPN, 1, [Define to 1 if libcurl has CURLOPT_SSL_ENABLE_ALPN CURLoption])
AC_MSG_RESULT(yes)
],
[AC_DEFINE(HAVE_CURLOPT_SSL_ENABLE_ALPN, 0, [Define to 1 if libcurl has CURLOPT_SSL_ENABLE_ALPN CURLoption])
AC_MSG_RESULT(no)
]
)
dnl CURLOPT_KEEP_SENDING_ON_ERROR (is supported by 7.51.0 and later)
AC_MSG_CHECKING([checking CURLOPT_KEEP_SENDING_ON_ERROR])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[#include <curl/curl.h>]],
[[CURLoption opt = CURLOPT_KEEP_SENDING_ON_ERROR;]])
],
[AC_DEFINE(HAVE_CURLOPT_KEEP_SENDING_ON_ERROR, 1, [Define to 1 if libcurl has CURLOPT_KEEP_SENDING_ON_ERROR CURLoption])
AC_MSG_RESULT(yes)
],
[AC_DEFINE(HAVE_CURLOPT_KEEP_SENDING_ON_ERROR, 0, [Define to 1 if libcurl has CURLOPT_KEEP_SENDING_ON_ERROR CURLoption])
AC_MSG_RESULT(no)
]
)
dnl ----------------------------------------------
dnl output files
dnl ----------------------------------------------
AC_CONFIG_FILES(Makefile src/Makefile test/Makefile doc/Makefile)
dnl ----------------------------------------------
dnl short commit hash
dnl ----------------------------------------------
AC_CHECK_PROG([GITCMD], [git —version], [yes], [no])
AS_IF([test -d .git], [DOTGITDIR=yes], [DOTGITDIR=no])
AC_MSG_CHECKING([github short commit hash])
if test "x${GITCMD}" = "xyes" -a "x${DOTGITDIR}" = "xyes"; then
GITCOMMITHASH=`git rev-parse --short HEAD`
elif test -f default_commit_hash; then
GITCOMMITHASH=`cat default_commit_hash`
else
GITCOMMITHASH="unknown"
fi
AC_MSG_RESULT([${GITCOMMITHASH}])
AC_DEFINE_UNQUOTED([COMMIT_HASH_VAL], ["${GITCOMMITHASH}"], [short commit hash value on github])
dnl ----------------------------------------------
dnl put
dnl ----------------------------------------------
AC_OUTPUT
dnl ----------------------------------------------
dnl end configuration
dnl ----------------------------------------------
#
# Local variables:
# tab-width: 4
# c-basic-offset: 4
# End:
# vim600: expandtab sw=4 ts= fdm=marker
# vim<600: expandtab sw=4 ts=4
#

View File

@ -5,15 +5,25 @@ S3FS \- FUSE-based file system backed by Amazon S3
.SS mounting
.TP
\fBs3fs bucket[:/path] mountpoint \fP [options]
.TP
\fBs3fs mountpoint \fP [options (must specify bucket= option)]
.SS unmounting
.TP
\fBumount mountpoint
.SS utility mode ( remove interrupted multipart uploading objects )
For root.
.TP
\fBs3fs -u bucket
\fBfusermount -u mountpoint
For unprivileged user.
.SS utility mode (remove interrupted multipart uploading objects)
.TP
\fBs3fs --incomplete-mpu-list (-u) bucket
.TP
\fBs3fs --incomplete-mpu-abort[=all | =<expire date format>] bucket
.SH DESCRIPTION
s3fs is a FUSE filesystem that allows you to mount an Amazon S3 bucket as a local filesystem. It stores files natively and transparently in S3 (i.e., you can use other programs to access the same files).
.SH AUTHENTICATION
s3fs supports the standard AWS credentials file (https://docs.aws.amazon.com/cli/latest/userguide/cli-config-files.html) stored in `${HOME}/.aws/credentials`.
Alternatively, s3fs supports a custom passwd file. Only AWS credentials file format can be used when AWS session token is required.
The s3fs password file has this format (use this format if you have only one set of credentials):
.RS 4
\fBaccessKeyId\fP:\fBsecretAccessKey\fP
@ -29,6 +39,8 @@ Password files can be stored in two locations:
\fB/etc/passwd-s3fs\fP [0640]
\fB$HOME/.passwd-s3fs\fP [0600]
.RE
.PP
s3fs also recognizes the \fBAWS_ACCESS_KEY_ID\fP and \fBAWS_SECRET_ACCESS_KEY\fP environment variables.
.SH OPTIONS
.SS "general options"
.TP
@ -42,158 +54,382 @@ print version
FUSE foreground option - do not run as daemon.
.TP
\fB\-s\fR
FUSE singlethreaded option (disables multi-threaded operation)
FUSE single-threaded option (disables multi-threaded operation)
.SS "mount options"
.TP
All s3fs options must given in the form where "opt" is:
<option_name>=<option_value>
.TP
\fB\-o\fR bucket
if it is not specified bucket name (and path) in command line, must specify this option after \-o option for bucket name.
.TP
\fB\-o\fR default_acl (default="private")
the default canned acl to apply to all written S3 objects, e.g., "public-read".
Any created files will have this canned acl.
Any updated files will also have this canned acl applied!
the default canned acl to apply to all written s3 objects, e.g., "private", "public-read".
see https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#canned-acl for the full list of canned acls.
.TP
\fB\-o\fR prefix (default="") (coming soon!)
a prefix to append to all S3 objects.
.TP
\fB\-o\fR retries (default="2")
\fB\-o\fR retries (default="5")
number of times to retry a failed S3 transaction.
.TP
\fB\-o\fR tmpdir (default="/tmp")
local folder for temporary files.
.TP
\fB\-o\fR use_cache (default="" which means disabled)
local folder to use for local file cache.
.TP
\fB\-o\fR check_cache_dir_exist (default is disable)
If use_cache is set, check if the cache directory exists.
If this option is not specified, it will be created at runtime when the cache directory does not exist.
.TP
\fB\-o\fR del_cache - delete local file cache
delete local file cache when s3fs starts and exits.
.TP
\fB\-o\fR storage_class (default="standard")
store object with specified storage class.
Possible values: standard, standard_ia, onezone_ia, reduced_redundancy, intelligent_tiering, glacier, and deep_archive.
.TP
\fB\-o\fR use_rrs (default is disable)
use Amazon's Reduced Redundancy Storage.
this option can not be specified with use_sse.
(can specify use_rrs=1 for old version)
this option has been replaced by new storage_class option.
.TP
\fB\-o\fR use_sse (default is disable)
use Amazon<EFBFBD>fs Server-Site Encryption or Server-Side Encryption with Customer-Provided Encryption Keys.
this option can not be specified with use_rrs. specifying only "use_sse" or "use_sse=1" enables Server-Side Encryption.(use_sse=1 for old version)
specifying this option with file path which has some SSE-C secret key enables Server-Side Encryption with Customer-Provided Encryption Keys.(use_sse=file)
the file must be 600 permission. the file can have some lines, each line is one SSE-C key. the first line in file is used as Customer-Provided Encryption Keys for uploading and change headers etc.
if there are some keys after first line, those are used downloading object which are encripted by not first key.
so that, you can keep all SSE-C keys in file, that is SSE-C key history.
if AWSSSECKEYS environment is set, you can set SSE-C key instead of this option.
Specify three type Amazon's Server-Site Encryption: SSE-S3, SSE-C or SSE-KMS. SSE-S3 uses Amazon S3-managed encryption keys, SSE-C uses customer-provided encryption keys, and SSE-KMS uses the master key which you manage in AWS KMS.
You can specify "use_sse" or "use_sse=1" enables SSE-S3 type (use_sse=1 is old type parameter).
Case of setting SSE-C, you can specify "use_sse=custom", "use_sse=custom:<custom key file path>" or "use_sse=<custom key file path>" (only <custom key file path> specified is old type parameter).
You can use "c" for short "custom".
The custom key file must be 600 permission. The file can have some lines, each line is one SSE-C key.
The first line in file is used as Customer-Provided Encryption Keys for uploading and changing headers etc.
If there are some keys after first line, those are used downloading object which are encrypted by not first key.
So that, you can keep all SSE-C keys in file, that is SSE-C key history.
If you specify "custom" ("c") without file path, you need to set custom key by load_sse_c option or AWSSSECKEYS environment. (AWSSSECKEYS environment has some SSE-C keys with ":" separator.)
This option is used to decide the SSE type.
So that if you do not want to encrypt a object at uploading, but you need to decrypt encrypted object at downloading, you can use load_sse_c option instead of this option.
For setting SSE-KMS, specify "use_sse=kmsid" or "use_sse=kmsid:<kms id>".
You can use "k" for short "kmsid".
If you san specify SSE-KMS type with your <kms id> in AWS KMS, you can set it after "kmsid:" (or "k:").
If you specify only "kmsid" ("k"), you need to set AWSSSEKMSID environment which value is <kms id>.
You must be careful about that you can not use the KMS id which is not same EC2 region.
.TP
\fB\-o\fR load_sse_c - specify SSE-C keys
Specify the custom-provided encryption keys file path for decrypting at downloading.
If you use the custom-provided encryption key at uploading, you specify with "use_sse=custom".
The file has many lines, one line means one custom key.
So that you can keep all SSE-C keys in file, that is SSE-C key history.
AWSSSECKEYS environment is as same as this file contents.
.TP
\fB\-o\fR passwd_file (default="")
specify the path to the password file, which which takes precedence over the password in $HOME/.passwd-s3fs and /etc/passwd-s3fs
.TP
\fB\-o\fR ahbe_conf (default="" which means disabled)
This option specifies the configuration file path which file is the additional HTTP header by file(object) extension.
This option specifies the configuration file path which file is the additional HTTP header by file (object) extension.
The configuration file format is below:
-----------
line = [file suffix] HTTP-header [HTTP-values]
file suffix = file(object) suffix, if this field is empty, it means "*"(all object).
line = [file suffix or regex] HTTP-header [HTTP-values]
file suffix = file (object) suffix, if this field is empty, it means "reg:(.*)".(=all object).
regex = regular expression to match the file (object) path. this type starts with "reg:" prefix.
HTTP-header = additional HTTP header name
HTTP-values = additional HTTP header value
-----------
Sample:
-----------
.gz Content-Encoding gzip
.Z Content-Encoding compress
X-S3FS-MYHTTPHEAD myvalue
.gz Content-Encoding gzip
.Z Content-Encoding compress
reg:^/MYDIR/(.*)[.]t2$ Content-Encoding text2
-----------
A sample configuration file is uploaded in "test" directory.
If you specify this option for set "Content-Encoding" HTTP header, please take care for RFC 2616.
.TP
\fB\-o\fR profile (default="default")
Choose a profile from ${HOME}/.aws/credentials to authenticate against S3.
Note that this format matches the AWS CLI format and differs from the s3fs passwd format.
.TP
\fB\-o\fR public_bucket (default="" which means disabled)
anonymously mount a public bucket when set to 1, ignores the $HOME/.passwd-s3fs and /etc/passwd-s3fs files.
S3 does not allow copy object api for anonymous users, then s3fs sets nocopyapi option automatically when public_bucket=1 option is specified.
.TP
\fB\-o\fR connect_timeout (default="10" seconds)
\fB\-o\fR connect_timeout (default="300" seconds)
time to wait for connection before giving up.
.TP
\fB\-o\fR readwrite_timeout (default="30" seconds)
\fB\-o\fR readwrite_timeout (default="120" seconds)
time to wait between read/write activity before giving up.
.TP
\fB\-o\fR max_stat_cache_size (default="1000" entries (about 4MB))
maximum number of entries in the stat cache
\fB\-o\fR list_object_max_keys (default="1000")
specify the maximum number of keys returned by S3 list object API. The default is 1000. you can set this value to 1000 or more.
.TP
\fB\-o\fR stat_cache_expire (default is no expire)
specify expire time(seconds) for entries in the stat cache
\fB\-o\fR max_stat_cache_size (default="100,000" entries (about 40MB))
maximum number of entries in the stat cache and symbolic link cache.
.TP
\fB\-o\fR stat_cache_expire (default is 900)
specify expire time (seconds) for entries in the stat cache and symbolic link cache. This expire time indicates the time since cached.
.TP
\fB\-o\fR stat_cache_interval_expire (default is 900)
specify expire time (seconds) for entries in the stat cache and symbolic link cache. This expire time is based on the time from the last access time of those cache.
This option is exclusive with stat_cache_expire, and is left for compatibility with older versions.
.TP
\fB\-o\fR enable_noobj_cache (default is disable)
enable cache entries for the object which does not exist.
s3fs always has to check whether file(or sub directory) exists under object(path) when s3fs does some command, since s3fs has recognized a directory which does not exist and has files or sub directories under itself.
s3fs always has to check whether file (or sub directory) exists under object (path) when s3fs does some command, since s3fs has recognized a directory which does not exist and has files or sub directories under itself.
It increases ListBucket request and makes performance bad.
You can specify this option for performance, s3fs memorizes in stat cache that the object(file or directory) does not exist.
You can specify this option for performance, s3fs memorizes in stat cache that the object (file or directory) does not exist.
.TP
\fB\-o\fR nodnscache - disable dns cache.
s3fs is always using dns cache, this option make dns cache disable.
\fB\-o\fR no_check_certificate (by default this option is disabled)
server certificate won't be checked against the available certificate authorities.
.TP
\fB\-o\fR nosscache - disable ssl session cache.
s3fs is always using ssl session cache, this option make ssl session cache disable.
\fB\-o\fR ssl_verify_hostname (default="2")
When 0, do not verify the SSL certificate against the hostname.
.TP
\fB\-o\fR nodnscache - disable DNS cache.
s3fs is always using DNS cache, this option make DNS cache disable.
.TP
\fB\-o\fR nosscache - disable SSL session cache.
s3fs is always using SSL session cache, this option make SSL session cache disable.
.TP
\fB\-o\fR multireq_max (default="20")
maximum number of parallel request for listing objects.
.TP
\fB\-o\fR parallel_count (default="5")
number of parallel request for uploading big objects.
s3fs uploads large object(default:over 20MB) by multipart post request, and sends parallel requests.
s3fs uploads large object (over 20MB) by multipart post request, and sends parallel requests.
This option limits parallel request count which s3fs requests at once.
It is necessary to set this value depending on a CPU and a network band.
This option is lated to fd_page_size option and affects it.
.TP
\fB\-o\fR fd_page_size(default="52428800"(50MB))
number of internal management page size for each file discriptor.
For delayed reading and writing by s3fs, s3fs manages pages which is separated from object. Each pages has a status that data is already loaded(or not loaded yet).
This option should not be changed when you don't have a trouble with performance.
This value is changed automatically by parallel_count and multipart_size values(fd_page_size value = parallel_count * multipart_size).
\fB\-o\fR multipart_size (default="10")
part size, in MB, for each multipart request.
The minimum value is 5 MB and the maximum value is 5 GB.
.TP
\fB\-o\fR multipart_size(default="10"(10MB))
number of one part size in multipart uploading request.
The default size is 10MB(10485760byte), this value is minimum size.
Specify number of MB and over 10(MB).
This option is lated to fd_page_size option and affects it.
\fB\-o\fR multipart_copy_size (default="512")
part size, in MB, for each multipart copy request, used for
renames and mixupload.
The minimum value is 5 MB and the maximum value is 5 GB.
Must be at least 512 MB to copy the maximum 5 TB object size
but lower values may improve performance.
.TP
\fB\-o\fR url (default="http://s3.amazonaws.com")
sets the url to use to access Amazon S3. If you want to use HTTPS, then you can set url=https://s3.amazonaws.com
\fB\-o\fR max_dirty_data (default="5120")
Flush dirty data to S3 after a certain number of MB written.
The minimum value is 50 MB. -1 value means disable.
Cannot be used with nomixupload.
.TP
\fB\-o\fR ensure_diskfree (default 0)
sets MB to ensure disk free space. This option means the threshold of free space size on disk which is used for the cache file by s3fs.
s3fs makes file for downloading, uploading and caching files.
If the disk free space is smaller than this value, s3fs do not use diskspace as possible in exchange for the performance.
.TP
\fB\-o\fR multipart_threshold (default="25")
threshold, in MB, to use multipart upload instead of
single-part. Must be at least 5 MB.
.TP
\fB\-o\fR singlepart_copy_limit (default="512")
maximum size, in MB, of a single-part copy before trying
multipart copy.
.TP
\fB\-o\fR host (default="https://s3.amazonaws.com")
Set a non-Amazon host, e.g., https://example.com.
.TP
\fB\-o\fR servicepath (default="/")
Set a service path when the non-Amazon host requires a prefix.
.TP
\fB\-o\fR url (default="https://s3.amazonaws.com")
sets the url to use to access Amazon S3. If you want to use HTTP, then you can set "url=http://s3.amazonaws.com".
If you do not use https, please specify the URL with the url option.
.TP
\fB\-o\fR endpoint (default="us-east-1")
sets the endpoint to use on signature version 4.
If this option is not specified, s3fs uses "us-east-1" region as the default.
If the s3fs could not connect to the region specified by this option, s3fs could not run.
But if you do not specify this option, and if you can not connect with the default region, s3fs will retry to automatically connect to the other region.
So s3fs can know the correct region name, because s3fs can find it in an error from the S3 server.
.TP
\fB\-o\fR sigv2 (default is signature version 4 falling back to version 2)
sets signing AWS requests by using only signature version 2.
.TP
\fB\-o\fR sigv4 (default is signature version 4 falling back to version 2)
sets signing AWS requests by using only signature version 4.
.TP
\fB\-o\fR mp_umask (default is "0000")
sets umask for the mount point directory.
If allow_other option is not set, s3fs allows access to the mount point only to the owner.
In the opposite case s3fs allows access to all users as the default.
But if you set the allow_other with this option, you can control the permissions of the mount point by this option like umask.
.TP
\fB\-o\fR umask (default is "0000")
sets umask for files under the mountpoint. This can allow
users other than the mounting user to read and write to files
that they did not create.
.TP
\fB\-o\fR nomultipart - disable multipart uploads
.TP
\fB\-o\fR enable_content_md5 ( default is disable )
verifying uploaded data without multipart by content-md5 header.
Enable to send "Content-MD5" header when uploading a object without multipart posting.
If this option is enabled, it has some influences on a performance of s3fs when uploading small object.
Because s3fs always checks MD5 when uploading large object, this option does not affect on large object.
\fB\-o\fR enable_content_md5 (default is disable)
Allow S3 server to check data integrity of uploads via the Content-MD5 header.
This can add CPU overhead to transfers.
.TP
\fB\-o\fR iam_role ( default is no role )
set the IAM Role that will supply the credentials from the instance meta-data.
\fB\-o\fR ecs (default is disable)
This option instructs s3fs to query the ECS container credential metadata address instead of the instance metadata address.
.TP
\fB\-o\fR noxmlns - disable registing xml name space.
disable registing xml name space for response of ListBucketResult and ListVersionsResult etc. Default name space is looked up from "http://s3.amazonaws.com/doc/2006-03-01".
\fB\-o\fR iam_role (default is no IAM role)
This option requires the IAM role name or "auto". If you specify "auto", s3fs will automatically use the IAM role names that are set to an instance. If you specify this option without any argument, it is the same as that you have specified the "auto".
.TP
\fB\-o\fR imdsv1only (default is to use IMDSv2 with fallback to v1)
AWS instance metadata service, used with IAM role authentication,
supports the use of an API token. If you're using an IAM role in an
environment that does not support IMDSv2, setting this flag will skip
retrieval and usage of the API token when retrieving IAM credentials.
.TP
\fB\-o\fR ibm_iam_auth (default is not using IBM IAM authentication)
This option instructs s3fs to use IBM IAM authentication. In this mode, the AWSAccessKey and AWSSecretKey will be used as IBM's Service-Instance-ID and APIKey, respectively.
.TP
\fB\-o\fR ibm_iam_endpoint (default is https://iam.cloud.ibm.com)
Sets the URL to use for IBM IAM authentication.
.TP
\fB\-o\fR use_xattr (default is not handling the extended attribute)
Enable to handle the extended attribute (xattrs).
If you set this option, you can use the extended attribute.
For example, encfs and ecryptfs need to support the extended attribute.
Notice: if s3fs handles the extended attribute, s3fs can not work to copy command with preserve=mode.
.TP
\fB\-o\fR noxmlns - disable registering xml name space.
disable registering xml name space for response of ListBucketResult and ListVersionsResult etc. Default name space is looked up from "http://s3.amazonaws.com/doc/2006-03-01".
This option should not be specified now, because s3fs looks up xmlns automatically after v1.66.
.TP
\fB\-o\fR nomixupload - disable copy in multipart uploads.
Disable to use PUT (copy api) when multipart uploading large size objects.
By default, when doing multipart upload, the range of unchanged data will use PUT (copy api) whenever possible.
When nocopyapi or norenameapi is specified, use of PUT (copy api) is invalidated even if this option is not specified.
.TP
\fB\-o\fR nocopyapi - for other incomplete compatibility object storage.
For a distributed object storage which is compatibility S3 API without PUT(copy api).
If you set this option, s3fs do not use PUT with "x-amz-copy-source"(copy api). Because traffic is increased 2-3 times by this option, we do not recommend this.
For a distributed object storage which is compatibility S3 API without PUT (copy api).
If you set this option, s3fs do not use PUT with "x-amz-copy-source" (copy api). Because traffic is increased 2-3 times by this option, we do not recommend this.
.TP
\fB\-o\fR norenameapi - for other incomplete compatibility object storage.
For a distributed object storage which is compatibility S3 API without PUT(copy api).
This option is a subset of nocopyapi option. The nocopyapi option does not use copy-api for all command(ex. chmod, chown, touch, mv, etc), but this option does not use copy-api for only rename command(ex. mv).
If this option is specified with nocopapi, the s3fs ignores it.
For a distributed object storage which is compatibility S3 API without PUT (copy api).
This option is a subset of nocopyapi option. The nocopyapi option does not use copy-api for all command (ex. chmod, chown, touch, mv, etc), but this option does not use copy-api for only rename command (ex. mv).
If this option is specified with nocopyapi, then s3fs ignores it.
.TP
\fB\-o\fR use_path_request_style (use legacy API calling style)
Enble compatibility with S3-like APIs which do not support the virtual-host request style, by using the older path request style.
Enable compatibility with S3-like APIs which do not support the virtual-host request style, by using the older path request style.
.TP
\fB\-o\fR listobjectsv2 (use ListObjectsV2)
Issue ListObjectsV2 instead of ListObjects, useful on object
stores without ListObjects support.
.TP
\fB\-o\fR noua (suppress User-Agent header)
Usually s3fs outputs of the User-Agent in "s3fs/<version> (commit hash <hash>; <using ssl library name>)" format.
If this option is specified, s3fs suppresses the output of the User-Agent.
.TP
\fB\-o\fR cipher_suites
Customize the list of TLS cipher suites. Expects a colon separated list of cipher suite names.
A list of available cipher suites, depending on your TLS engine, can be found on the CURL library documentation:
https://curl.haxx.se/docs/ssl-ciphers.html
.TP
\fB\-o\fR instance_name
The instance name of the current s3fs mountpoint.
This name will be added to logging messages and user agent headers sent by s3fs.
.TP
\fB\-o\fR complement_stat (complement lack of file/directory mode)
s3fs complements lack of information about file/directory mode if a file or a directory object does not have x-amz-meta-mode header.
As default, s3fs does not complements stat information for a object, then the object will not be able to be allowed to list/modify.
.TP
\fB\-o\fR notsup_compat_dir (not support compatibility directory types)
As a default, s3fs supports objects of the directory type as much as possible and recognizes them as directories.
Objects that can be recognized as directory objects are "dir/", "dir", "dir_$folder$", and there is a file object that does not have a directory object but contains that directory path.
s3fs needs redundant communication to support all these directory types.
The object as the directory created by s3fs is "dir/".
By restricting s3fs to recognize only "dir/" as a directory, communication traffic can be reduced.
This option is used to give this restriction to s3fs.
However, if there is a directory object other than "dir/" in the bucket, specifying this option is not recommended.
s3fs may not be able to recognize the object correctly if an object created by s3fs exists in the bucket.
Please use this option when the directory in the bucket is only "dir/" object.
.TP
\fB\-o\fR use_wtf8 - support arbitrary file system encoding.
S3 requires all object names to be valid UTF-8. But some
clients, notably Windows NFS clients, use their own encoding.
This option re-encodes invalid UTF-8 object names into valid
UTF-8 by mapping offending codes into a 'private' codepage of the
Unicode set.
Useful on clients not using UTF-8 as their file system encoding.
.TP
\fB\-o\fR use_session_token - indicate that session token should be provided.
If credentials are provided by environment variables this switch
forces presence check of AWS_SESSION_TOKEN variable.
Otherwise an error is returned.
.TP
\fB\-o\fR requester_pays (default is disable)
This option instructs s3fs to enable requests involving Requester Pays buckets (It includes the 'x-amz-request-payer=requester' entry in the request header).
.TP
\fB\-o\fR mime (default is "/etc/mime.types")
Specify the path of the mime.types file.
If this option is not specified, the existence of "/etc/mime.types" is checked, and that file is loaded as mime information.
If this file does not exist on macOS, then "/etc/apache2/mime.types" is checked as well.
.TP
\fB\-o\fR logfile - specify the log output file.
s3fs outputs the log file to syslog. Alternatively, if s3fs is started with the "-f" option specified, the log will be output to the stdout/stderr.
You can use this option to specify the log file that s3fs outputs.
If you specify a log file with this option, it will reopen the log file when s3fs receives a SIGHUP signal. You can use the SIGHUP signal for log rotation.
.TP
\fB\-o\fR dbglevel (default="crit")
Set the debug message level. set value as crit (critical), err (error), warn (warning), info (information) to debug level. default debug level is critical.
If s3fs run with "-d" option, the debug level is set information.
When s3fs catch the signal SIGUSR2, the debug level is bump up.
.TP
\fB\-o\fR curldbg - put curl debug message
Put the debug message from libcurl when this option is specified.
Specify "normal" or "body" for the parameter.
If the parameter is omitted, it is the same as "normal".
If "body" is specified, some API communication body data will be output in addition to the debug message output as "normal".
.TP
\fB\-o\fR no_time_stamp_msg - no time stamp in debug message
The time stamp is output to the debug message by default.
If this option is specified, the time stamp will not be output in the debug message.
It is the same even if the environment variable "S3FS_MSGTIMESTAMP" is set to "no".
.TP
\fB\-o\fR set_check_cache_sigusr1 (default is stdout)
If the cache is enabled, you can check the integrity of the cache file and the cache file's stats info file.
This option is specified and when sending the SIGUSR1 signal to the s3fs process checks the cache status at that time.
This option can take a file path as parameter to output the check result to that file.
The file path parameter can be omitted. If omitted, the result will be output to stdout or syslog.
.SS "utility mode options"
.TP
\fB\-u\fR or \fB\-\-incomplete\-mpu\-list\fR
Lists multipart incomplete objects uploaded to the specified bucket.
.TP
\fB\-\-incomplete\-mpu\-abort\fR all or date format (default="24H")
Delete the multipart incomplete object uploaded to the specified bucket.
If "all" is specified for this option, all multipart incomplete objects will be deleted.
If you specify no argument as an option, objects older than 24 hours (24H) will be deleted (This is the default value).
You can specify an optional date format.
It can be specified as year, month, day, hour, minute, second, and it is expressed as "Y", "M", "D", "h", "m", "s" respectively.
For example, "1Y6M10D12h30m30s".
.SH FUSE/MOUNT OPTIONS
.TP
Most of the generic mount options described in 'man mount' are supported (ro, rw, suid, nosuid, dev, nodev, exec, noexec, atime, noatime, sync async, dirsync). Filesystems are mounted with '-onodev,nosuid' by default, which can only be overridden by a privileged user.
Most of the generic mount options described in 'man mount' are supported (ro, rw, suid, nosuid, dev, nodev, exec, noexec, atime, noatime, sync async, dirsync). Filesystems are mounted with '\-onodev,nosuid' by default, which can only be overridden by a privileged user.
.TP
There are many FUSE specific mount options that can be specified. e.g. allow_other. See the FUSE README for the full set.
.SH LOCAL STORAGE CONSUMPTION
.TP
s3fs requires local caching for operation. You can enable a local cache with "\-o use_cache" or s3fs uses temporary files to cache pending requests to s3.
.TP
Apart from the requirements discussed below, it is recommended to keep enough cache resp. temporary storage to allow one copy each of all files open for reading and writing at any one time.
.TP
.SS Local cache with \[dq]\-o use_cache\[dq]
.TP
s3fs automatically maintains a local cache of files. The cache folder is specified by the parameter of "\-o use_cache". It is only a local cache that can be deleted at any time. s3fs rebuilds it if necessary.
.TP
Whenever s3fs needs to read or write a file on S3, it first creates the file in the cache directory and operates on it.
.TP
The amount of local cache storage used can be indirectly controlled with "\-o ensure_diskfree".
.TP
.SS Without local cache
.TP
Since s3fs always requires some storage space for operation, it creates temporary files to store incoming write requests until the required s3 request size is reached and the segment has been uploaded. After that, this data is truncated in the temporary file to free up storage space.
.TP
Per file you need at least twice the part size (default 5MB or "-o multipart_size") for writing multipart requests or space for the whole file if single requests are enabled ("\-o nomultipart").
.SH NOTES
.TP
Maximum file size=64GB (limited by s3fs, not Amazon).
.TP
If enabled via the "use_cache" option, s3fs automatically maintains a local cache of files in the folder specified by use_cache. Whenever s3fs needs to read or write a file on S3, it first downloads the entire file locally to the folder specified by use_cache and operates on it. When fuse_release() is called, s3fs will re-upload the file to S3 if it has been changed. s3fs uses md5 checksums to minimize downloads from S3.
.TP
The folder specified by use_cache is just a local cache. It can be deleted at any time. s3fs rebuilds it on demand.
.TP
Local file caching works by calculating and comparing md5 checksums (ETag HTTP header).
The maximum size of objects that s3fs can handle depends on Amazon S3. For example, up to 5 GB when using single PUT API. And up to 5 TB is supported when Multipart Upload API is used.
.TP
s3fs leverages /etc/mime.types to "guess" the "correct" content-type based on file name extension. This means that you can copy a website to S3 and serve it up directly from S3 with correct content-types!
.SH SEE ALSO
fuse(8), mount(8), fusermount(1), fstab(5)
.SH BUGS
Due to S3's "eventual consistency" limitations, file creation can and will occasionally fail. Even after a successful create, subsequent reads can fail for an indeterminate time, even after one or more successful reads. Create and read enough files and you will eventually encounter this failure. This is not a flaw in s3fs and it is not something a FUSE wrapper like s3fs can work around. The retries option does not address this issue. Your application must either tolerate or compensate for these failures, for example by retrying creates or reads.
.SH AUTHOR

BIN
doc/s3fs.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -21,19 +21,91 @@ bin_PROGRAMS=s3fs
AM_CPPFLAGS = $(DEPS_CFLAGS)
if USE_GNUTLS_NETTLE
AM_CPPFLAGS += -DUSE_GNUTLS_NETTLE
AM_CPPFLAGS += -DUSE_GNUTLS_NETTLE
endif
s3fs_SOURCES = s3fs.cpp s3fs.h curl.cpp curl.h cache.cpp cache.h string_util.cpp string_util.h s3fs_util.cpp s3fs_util.h fdcache.cpp fdcache.h common_auth.cpp s3fs_auth.h common.h
s3fs_SOURCES = \
s3fs.cpp \
s3fs_global.cpp \
s3fs_help.cpp \
s3fs_logger.cpp \
s3fs_xml.cpp \
metaheader.cpp \
mpu_util.cpp \
mvnode.cpp \
curl.cpp \
curl_handlerpool.cpp \
curl_multi.cpp \
curl_util.cpp \
bodydata.cpp \
s3objlist.cpp \
cache.cpp \
string_util.cpp \
s3fs_util.cpp \
fdcache.cpp \
fdcache_entity.cpp \
fdcache_page.cpp \
fdcache_stat.cpp \
fdcache_auto.cpp \
fdcache_fdinfo.cpp \
fdcache_pseudofd.cpp \
fdcache_untreated.cpp \
addhead.cpp \
sighandlers.cpp \
autolock.cpp \
common_auth.cpp
if USE_SSL_OPENSSL
s3fs_SOURCES += openssl_auth.cpp
s3fs_SOURCES += openssl_auth.cpp
endif
if USE_SSL_GNUTLS
s3fs_SOURCES += gnutls_auth.cpp
s3fs_SOURCES += gnutls_auth.cpp
endif
if USE_SSL_NSS
s3fs_SOURCES += nss_auth.cpp
s3fs_SOURCES += nss_auth.cpp
endif
s3fs_LDADD = $(DEPS_LIBS)
noinst_PROGRAMS = \
test_curl_util \
test_page_list \
test_string_util
test_curl_util_SOURCES = common_auth.cpp curl_util.cpp string_util.cpp test_curl_util.cpp s3fs_global.cpp s3fs_logger.cpp
if USE_SSL_OPENSSL
test_curl_util_SOURCES += openssl_auth.cpp
endif
if USE_SSL_GNUTLS
test_curl_util_SOURCES += gnutls_auth.cpp
endif
if USE_SSL_NSS
test_curl_util_SOURCES += nss_auth.cpp
endif
test_curl_util_LDADD = $(DEPS_LIBS)
test_page_list_SOURCES = \
fdcache_page.cpp \
s3fs_global.cpp \
s3fs_logger.cpp \
string_util.cpp \
test_page_list.cpp
test_string_util_SOURCES = string_util.cpp test_string_util.cpp s3fs_logger.cpp
TESTS = \
test_curl_util \
test_page_list \
test_string_util
clang-tidy:
clang-tidy $(s3fs_SOURCES) -- $(DEPS_CFLAGS) $(CPPFLAGS)
#
# Local variables:
# tab-width: 4
# c-basic-offset: 4
# End:
# vim600: expandtab sw=4 ts= fdm=marker
# vim<600: expandtab sw=4 ts=4
#

278
src/addhead.cpp Normal file
View File

@ -0,0 +1,278 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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 <cstdio>
#include <cstdlib>
#include <sstream>
#include <fstream>
#include "common.h"
#include "s3fs.h"
#include "addhead.h"
#include "curl_util.h"
//-------------------------------------------------------------------
// Symbols
//-------------------------------------------------------------------
#define ADD_HEAD_REGEX "reg:"
//-------------------------------------------------------------------
// Class AdditionalHeader
//-------------------------------------------------------------------
AdditionalHeader AdditionalHeader::singleton;
//-------------------------------------------------------------------
// Class AdditionalHeader method
//-------------------------------------------------------------------
AdditionalHeader::AdditionalHeader()
{
if(this == AdditionalHeader::get()){
is_enable = false;
}else{
abort();
}
}
AdditionalHeader::~AdditionalHeader()
{
if(this == AdditionalHeader::get()){
Unload();
}else{
abort();
}
}
bool AdditionalHeader::Load(const char* file)
{
if(!file){
S3FS_PRN_WARN("file is NULL.");
return false;
}
Unload();
std::ifstream AH(file);
if(!AH.good()){
S3FS_PRN_WARN("Could not open file(%s).", file);
return false;
}
// read file
std::string line;
ADDHEAD *paddhead;
while(getline(AH, line)){
if(line.empty()){
continue;
}
if('#' == line[0]){
continue;
}
// load a line
std::istringstream ss(line);
std::string key; // suffix(key)
std::string head; // additional HTTP header
std::string value; // header value
if(0 == isblank(line[0])){
ss >> key;
}
if(ss){
ss >> head;
if(ss && static_cast<size_t>(ss.tellg()) < line.size()){
value = line.substr(static_cast<int>(ss.tellg()) + 1);
}
}
// check it
if(head.empty()){
if(key.empty()){
continue;
}
S3FS_PRN_ERR("file format error: %s key(suffix) is no HTTP header value.", key.c_str());
Unload();
return false;
}
paddhead = new ADDHEAD;
if(0 == strncasecmp(key.c_str(), ADD_HEAD_REGEX, strlen(ADD_HEAD_REGEX))){
// regex
if(key.size() <= strlen(ADD_HEAD_REGEX)){
S3FS_PRN_ERR("file format error: %s key(suffix) does not have key std::string.", key.c_str());
delete paddhead;
continue;
}
key.erase(0, strlen(ADD_HEAD_REGEX));
// compile
regex_t* preg = new regex_t;
int result;
if(0 != (result = regcomp(preg, key.c_str(), REG_EXTENDED | REG_NOSUB))){ // we do not need matching info
char errbuf[256];
regerror(result, preg, errbuf, sizeof(errbuf));
S3FS_PRN_ERR("failed to compile regex from %s key by %s.", key.c_str(), errbuf);
delete preg;
delete paddhead;
continue;
}
// set
paddhead->pregex = preg;
paddhead->basestring = key;
paddhead->headkey = head;
paddhead->headvalue = value;
}else{
// not regex, directly comparing
paddhead->pregex = NULL;
paddhead->basestring = key;
paddhead->headkey = head;
paddhead->headvalue = value;
}
// add list
addheadlist.push_back(paddhead);
// set flag
if(!is_enable){
is_enable = true;
}
}
return true;
}
void AdditionalHeader::Unload()
{
is_enable = false;
for(addheadlist_t::iterator iter = addheadlist.begin(); iter != addheadlist.end(); ++iter){
ADDHEAD *paddhead = *iter;
if(paddhead){
if(paddhead->pregex){
regfree(paddhead->pregex);
delete paddhead->pregex;
}
delete paddhead;
}
}
addheadlist.clear();
}
bool AdditionalHeader::AddHeader(headers_t& meta, const char* path) const
{
if(!is_enable){
return true;
}
if(!path){
S3FS_PRN_WARN("path is NULL.");
return false;
}
size_t pathlength = strlen(path);
// loop
//
// [NOTE]
// Because to allow duplicate key, and then scanning the entire table.
//
for(addheadlist_t::const_iterator iter = addheadlist.begin(); iter != addheadlist.end(); ++iter){
const ADDHEAD *paddhead = *iter;
if(!paddhead){
continue;
}
if(paddhead->pregex){
// regex
regmatch_t match; // not use
if(0 == regexec(paddhead->pregex, path, 1, &match, 0)){
// match -> adding header
meta[paddhead->headkey] = paddhead->headvalue;
}
}else{
// directly comparing
if(paddhead->basestring.length() < pathlength){
if(paddhead->basestring.empty() || 0 == strcmp(&path[pathlength - paddhead->basestring.length()], paddhead->basestring.c_str())){
// match -> adding header
meta[paddhead->headkey] = paddhead->headvalue;
}
}
}
}
return true;
}
struct curl_slist* AdditionalHeader::AddHeader(struct curl_slist* list, const char* path) const
{
headers_t meta;
if(!AddHeader(meta, path)){
return list;
}
for(headers_t::iterator iter = meta.begin(); iter != meta.end(); ++iter){
// Adding header
list = curl_slist_sort_insert(list, iter->first.c_str(), iter->second.c_str());
}
meta.clear();
S3FS_MALLOCTRIM(0);
return list;
}
bool AdditionalHeader::Dump() const
{
if(!S3fsLog::IsS3fsLogDbg()){
return true;
}
std::ostringstream ssdbg;
int cnt = 1;
ssdbg << "Additional Header list[" << addheadlist.size() << "] = {" << std::endl;
for(addheadlist_t::const_iterator iter = addheadlist.begin(); iter != addheadlist.end(); ++iter, ++cnt){
const ADDHEAD *paddhead = *iter;
ssdbg << " [" << cnt << "] = {" << std::endl;
if(paddhead){
if(paddhead->pregex){
ssdbg << " type\t\t--->\tregex" << std::endl;
}else{
ssdbg << " type\t\t--->\tsuffix matching" << std::endl;
}
ssdbg << " base std::string\t--->\t" << paddhead->basestring << std::endl;
ssdbg << " add header\t--->\t" << paddhead->headkey << ": " << paddhead->headvalue << std::endl;
}
ssdbg << " }" << std::endl;
}
ssdbg << "}" << std::endl;
// print all
S3FS_PRN_DBG("%s", ssdbg.str().c_str());
return true;
}
/*
* 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
*/

75
src/addhead.h Normal file
View File

@ -0,0 +1,75 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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.
*/
#ifndef S3FS_ADDHEAD_H_
#define S3FS_ADDHEAD_H_
#include <regex.h>
#include "metaheader.h"
//----------------------------------------------
// Structure / Typedef
//----------------------------------------------
typedef struct add_header{
regex_t* pregex; // not NULL means using regex, NULL means comparing suffix directly.
std::string basestring;
std::string headkey;
std::string headvalue;
}ADDHEAD;
typedef std::vector<ADDHEAD *> addheadlist_t;
//----------------------------------------------
// Class AdditionalHeader
//----------------------------------------------
class AdditionalHeader
{
private:
static AdditionalHeader singleton;
bool is_enable;
addheadlist_t addheadlist;
protected:
AdditionalHeader();
~AdditionalHeader();
public:
// Reference singleton
static AdditionalHeader* get() { return &singleton; }
bool Load(const char* file);
void Unload();
bool AddHeader(headers_t& meta, const char* path) const;
struct curl_slist* AddHeader(struct curl_slist* list, const char* path) const;
bool Dump() const;
};
#endif // S3FS_ADDHEAD_H_
/*
* 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
*/

80
src/autolock.cpp Normal file
View File

@ -0,0 +1,80 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Takeshi Nakatani <ggtakec.com>
*
* 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 <cstdio>
#include <cstdlib>
#include <cerrno>
#include "common.h"
#include "s3fs.h"
#include "autolock.h"
//-------------------------------------------------------------------
// Class AutoLock
//-------------------------------------------------------------------
AutoLock::AutoLock(pthread_mutex_t* pmutex, Type type) : auto_mutex(pmutex)
{
if (type == ALREADY_LOCKED) {
is_lock_acquired = false;
} else if (type == NO_WAIT) {
int result = pthread_mutex_trylock(auto_mutex);
if(result == 0){
is_lock_acquired = true;
}else if(result == EBUSY){
is_lock_acquired = false;
}else{
S3FS_PRN_CRIT("pthread_mutex_trylock returned: %d", result);
abort();
}
} else {
int result = pthread_mutex_lock(auto_mutex);
if(result == 0){
is_lock_acquired = true;
}else{
S3FS_PRN_CRIT("pthread_mutex_lock returned: %d", result);
abort();
}
}
}
bool AutoLock::isLockAcquired() const
{
return is_lock_acquired;
}
AutoLock::~AutoLock()
{
if (is_lock_acquired) {
int result = pthread_mutex_unlock(auto_mutex);
if(result != 0){
S3FS_PRN_CRIT("pthread_mutex_lock returned: %d", result);
abort();
}
}
}
/*
* 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
*/

60
src/autolock.h Normal file
View File

@ -0,0 +1,60 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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.
*/
#ifndef S3FS_AUTOLOCK_H_
#define S3FS_AUTOLOCK_H_
#include <pthread.h>
//-------------------------------------------------------------------
// AutoLock Class
//-------------------------------------------------------------------
class AutoLock
{
public:
enum Type {
NO_WAIT = 1,
ALREADY_LOCKED = 2,
NONE = 0
};
private:
pthread_mutex_t* const auto_mutex;
bool is_lock_acquired;
private:
AutoLock(const AutoLock&);
public:
explicit AutoLock(pthread_mutex_t* pmutex, Type type = NONE);
~AutoLock();
bool isLockAcquired() const;
};
#endif // S3FS_AUTOLOCK_H_
/*
* 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
*/

122
src/bodydata.cpp Normal file
View File

@ -0,0 +1,122 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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 <cstdio>
#include <cstdlib>
#include "common.h"
#include "s3fs.h"
#include "bodydata.h"
//-------------------------------------------------------------------
// Variables
//-------------------------------------------------------------------
static const int BODYDATA_RESIZE_APPEND_MIN = 1024;
static const int BODYDATA_RESIZE_APPEND_MID = 1024 * 1024;
static const int BODYDATA_RESIZE_APPEND_MAX = 10 * 1024 * 1024;
//-------------------------------------------------------------------
// Utility Functions
//-------------------------------------------------------------------
static size_t adjust_block(size_t bytes, size_t block)
{
return ((bytes / block) + ((bytes % block) ? 1 : 0)) * block;
}
//-------------------------------------------------------------------
// Class BodyData
//-------------------------------------------------------------------
bool BodyData::Resize(size_t addbytes)
{
if(IsSafeSize(addbytes)){
return true;
}
// New size
size_t need_size = adjust_block((lastpos + addbytes + 1) - bufsize, sizeof(off_t));
if(BODYDATA_RESIZE_APPEND_MAX < bufsize){
need_size = (BODYDATA_RESIZE_APPEND_MAX < need_size ? need_size : BODYDATA_RESIZE_APPEND_MAX);
}else if(BODYDATA_RESIZE_APPEND_MID < bufsize){
need_size = (BODYDATA_RESIZE_APPEND_MID < need_size ? need_size : BODYDATA_RESIZE_APPEND_MID);
}else if(BODYDATA_RESIZE_APPEND_MIN < bufsize){
need_size = ((bufsize * 2) < need_size ? need_size : (bufsize * 2));
}else{
need_size = (BODYDATA_RESIZE_APPEND_MIN < need_size ? need_size : BODYDATA_RESIZE_APPEND_MIN);
}
// realloc
char* newtext;
if(NULL == (newtext = (char*)realloc(text, (bufsize + need_size)))){
S3FS_PRN_CRIT("not enough memory (realloc returned NULL)");
free(text);
text = NULL;
return false;
}
text = newtext;
bufsize += need_size;
return true;
}
void BodyData::Clear()
{
if(text){
free(text);
text = NULL;
}
lastpos = 0;
bufsize = 0;
}
bool BodyData::Append(void* ptr, size_t bytes)
{
if(!ptr){
return false;
}
if(0 == bytes){
return true;
}
if(!Resize(bytes)){
return false;
}
memcpy(&text[lastpos], ptr, bytes);
lastpos += bytes;
text[lastpos] = '\0';
return true;
}
const char* BodyData::str() const
{
if(!text){
static const char strnull[] = "";
return strnull;
}
return text;
}
/*
* 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
*/

72
src/bodydata.h Normal file
View File

@ -0,0 +1,72 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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.
*/
#ifndef S3FS_BODYDATA_H_
#define S3FS_BODYDATA_H_
//----------------------------------------------
// Class BodyData
//----------------------------------------------
// memory class for curl write memory callback
//
class BodyData
{
private:
char* text;
size_t lastpos;
size_t bufsize;
private:
bool IsSafeSize(size_t addbytes) const
{
return ((lastpos + addbytes + 1) > bufsize ? false : true);
}
bool Resize(size_t addbytes);
public:
BodyData() : text(NULL), lastpos(0), bufsize(0) {}
~BodyData()
{
Clear();
}
void Clear();
bool Append(void* ptr, size_t bytes);
bool Append(void* ptr, size_t blockSize, size_t numBlocks)
{
return Append(ptr, (blockSize * numBlocks));
}
const char* str() const;
size_t size() const
{
return lastpos;
}
};
#endif // S3FS_BODYDATA_H_
/*
* 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
*/

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright 2007-2008 Randy Rizun <rrizun@gmail.com>
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,111 +17,170 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef S3FS_CACHE_H_
#define S3FS_CACHE_H_
#include "common.h"
#include "metaheader.h"
//-------------------------------------------------------------------
// Structure
//-------------------------------------------------------------------
//
// Struct
// Struct for stats cache
//
struct stat_cache_entry {
struct stat stbuf;
unsigned long hit_count;
time_t cache_date;
headers_t meta;
bool isforce;
bool noobjcache; // Flag: cache is no object for no listing.
struct stat stbuf;
unsigned long hit_count;
struct timespec cache_date;
headers_t meta;
bool isforce;
bool noobjcache; // Flag: cache is no object for no listing.
unsigned long notruncate; // 0<: not remove automatically at checking truncate
stat_cache_entry() : hit_count(0), cache_date(0), isforce(false), noobjcache(false) {
memset(&stbuf, 0, sizeof(struct stat));
meta.clear();
}
stat_cache_entry() : hit_count(0), isforce(false), noobjcache(false), notruncate(0L)
{
memset(&stbuf, 0, sizeof(struct stat));
cache_date.tv_sec = 0;
cache_date.tv_nsec = 0;
meta.clear();
}
};
typedef std::map<std::string, stat_cache_entry*> stat_cache_t; // key=path
//
// Class
// Struct for symbolic link cache
//
class StatCache
{
private:
static StatCache singleton;
static pthread_mutex_t stat_cache_lock;
stat_cache_t stat_cache;
bool IsExpireTime;
time_t ExpireTime;
unsigned long CacheSize;
bool IsCacheNoObject;
struct symlink_cache_entry {
std::string link;
unsigned long hit_count;
struct timespec cache_date; // The function that operates timespec uses the same as Stats
private:
void Clear(void);
bool GetStat(std::string& key, struct stat* pst, headers_t* meta, bool overcheck, const char* petag, bool* pisforce);
// Truncate stat cache
bool TruncateCache(void);
public:
StatCache();
~StatCache();
// Reference singleton
static StatCache* getStatCacheData(void) {
return &singleton;
}
// Attribute
unsigned long GetCacheSize(void) const;
unsigned long SetCacheSize(unsigned long size);
time_t GetExpireTime(void) const;
time_t SetExpireTime(time_t expire);
time_t UnsetExpireTime(void);
bool SetCacheNoObject(bool flag);
bool EnableCacheNoObject(void) {
return SetCacheNoObject(true);
}
bool DisableCacheNoObject(void) {
return SetCacheNoObject(false);
}
bool GetCacheNoObject(void) const {
return IsCacheNoObject;
}
// Get stat cache
bool GetStat(std::string& key, struct stat* pst, headers_t* meta, bool overcheck = true, bool* pisforce = NULL) {
return GetStat(key, pst, meta, overcheck, NULL, pisforce);
}
bool GetStat(std::string& key, struct stat* pst, bool overcheck = true) {
return GetStat(key, pst, NULL, overcheck, NULL, NULL);
}
bool GetStat(std::string& key, headers_t* meta, bool overcheck = true) {
return GetStat(key, NULL, meta, overcheck, NULL, NULL);
}
bool HasStat(std::string& key, bool overcheck = true) {
return GetStat(key, NULL, NULL, overcheck, NULL, NULL);
}
bool HasStat(std::string& key, const char* etag, bool overcheck = true) {
return GetStat(key, NULL, NULL, overcheck, etag, NULL);
}
// Cache For no object
bool IsNoObjectCache(std::string& key, bool overcheck = true);
bool AddNoObjectCache(std::string& key);
// Add stat cache
bool AddStat(std::string& key, headers_t& meta, bool forcedir = false);
// Delete stat cache
bool DelStat(const char* key);
bool DelStat(std::string& key) {
return DelStat(key.c_str());
symlink_cache_entry() : link(""), hit_count(0)
{
cache_date.tv_sec = 0;
cache_date.tv_nsec = 0;
}
};
typedef std::map<std::string, symlink_cache_entry*> symlink_cache_t;
//-------------------------------------------------------------------
// Class StatCache
//-------------------------------------------------------------------
// [NOTE] About Symbolic link cache
// The Stats cache class now also has a symbolic link cache.
// It is possible to take out the Symbolic link cache in another class,
// but the cache out etc. should be synchronized with the Stats cache
// and implemented in this class.
// Symbolic link cache size and timeout use the same settings as Stats
// cache. This simplifies user configuration, and from a user perspective,
// the symbolic link cache appears to be included in the Stats cache.
//
class StatCache
{
private:
static StatCache singleton;
static pthread_mutex_t stat_cache_lock;
stat_cache_t stat_cache;
bool IsExpireTime;
bool IsExpireIntervalType; // if this flag is true, cache data is updated at last access time.
time_t ExpireTime;
unsigned long CacheSize;
bool IsCacheNoObject;
symlink_cache_t symlink_cache;
private:
StatCache();
~StatCache();
void Clear();
bool GetStat(const std::string& key, struct stat* pst, headers_t* meta, bool overcheck, const char* petag, bool* pisforce);
// Truncate stat cache
bool TruncateCache();
// Truncate symbolic link cache
bool TruncateSymlink();
public:
// Reference singleton
static StatCache* getStatCacheData()
{
return &singleton;
}
// Attribute
unsigned long GetCacheSize() const;
unsigned long SetCacheSize(unsigned long size);
time_t GetExpireTime() const;
time_t SetExpireTime(time_t expire, bool is_interval = false);
time_t UnsetExpireTime();
bool SetCacheNoObject(bool flag);
bool EnableCacheNoObject()
{
return SetCacheNoObject(true);
}
bool DisableCacheNoObject()
{
return SetCacheNoObject(false);
}
bool GetCacheNoObject() const
{
return IsCacheNoObject;
}
// Get stat cache
bool GetStat(const std::string& key, struct stat* pst, headers_t* meta, bool overcheck = true, bool* pisforce = NULL)
{
return GetStat(key, pst, meta, overcheck, NULL, pisforce);
}
bool GetStat(const std::string& key, struct stat* pst, bool overcheck = true)
{
return GetStat(key, pst, NULL, overcheck, NULL, NULL);
}
bool GetStat(const std::string& key, headers_t* meta, bool overcheck = true)
{
return GetStat(key, NULL, meta, overcheck, NULL, NULL);
}
bool HasStat(const std::string& key, bool overcheck = true)
{
return GetStat(key, NULL, NULL, overcheck, NULL, NULL);
}
bool HasStat(const std::string& key, const char* etag, bool overcheck = true)
{
return GetStat(key, NULL, NULL, overcheck, etag, NULL);
}
// Cache For no object
bool IsNoObjectCache(const std::string& key, bool overcheck = true);
bool AddNoObjectCache(const std::string& key);
// Add stat cache
bool AddStat(const std::string& key, headers_t& meta, bool forcedir = false, bool no_truncate = false);
// Update meta stats
bool UpdateMetaStats(const std::string& key, headers_t& meta);
// Change no truncate flag
void ChangeNoTruncateFlag(const std::string& key, bool no_truncate);
// Delete stat cache
bool DelStat(const char* key, bool lock_already_held = false);
bool DelStat(const std::string& key, bool lock_already_held = false)
{
return DelStat(key.c_str(), lock_already_held);
}
// Cache for symbolic link
bool GetSymlink(const std::string& key, std::string& value);
bool AddSymlink(const std::string& key, const std::string& value);
bool DelSymlink(const char* key, bool lock_already_held = false);
};
//-------------------------------------------------------------------
// Functions
//
bool convert_header_to_stat(const char* path, headers_t& meta, struct stat* pst, bool forcedir = false);
//-------------------------------------------------------------------
bool convert_header_to_stat(const char* path, const headers_t& meta, struct stat* pst, bool forcedir = false);
#endif // S3FS_CACHE_H_
@ -130,6 +189,6 @@ bool convert_header_to_stat(const char* path, headers_t& meta, struct stat* pst,
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
* vim600: expandtab sw=4 ts=4 fdm=marker
* vim<600: expandtab sw=4 ts=4
*/

View File

@ -1,7 +1,7 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright 2007-2008 Randy Rizun <rrizun@gmail.com>
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,83 +17,37 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef S3FS_COMMON_H_
#define S3FS_COMMON_H_
//
// Macro
//
#define SAFESTRPTR(strptr) (strptr ? strptr : "")
#include <fcntl.h>
// for debug
#define FPRINT_NEST_SPACE_0 ""
#define FPRINT_NEST_SPACE_1 " "
#define FPRINT_NEST_SPACE_2 " "
#define FPRINT_NEST_CHECK(NEST) \
(0 == NEST ? FPRINT_NEST_SPACE_0 : 1 == NEST ? FPRINT_NEST_SPACE_1 : FPRINT_NEST_SPACE_2)
#include "../config.h"
#include "types.h"
#include "s3fs_logger.h"
#define LOWFPRINT(NEST, ...) \
printf("%s%s(%d): ", FPRINT_NEST_CHECK(NEST), __func__, __LINE__); \
printf(__VA_ARGS__); \
printf("\n"); \
//-------------------------------------------------------------------
// Global variables
//-------------------------------------------------------------------
// TODO: namespace these
static const int64_t FIVE_GB = 5LL * 1024LL * 1024LL * 1024LL;
static const off_t MIN_MULTIPART_SIZE = 5 * 1024 * 1024;
#define FPRINT(NEST, ...) \
if(foreground){ \
LOWFPRINT(NEST, __VA_ARGS__); \
}
#define FPRINT2(NEST, ...) \
if(foreground2){ \
LOWFPRINT(NEST, __VA_ARGS__); \
}
#define LOWSYSLOGPRINT(LEVEL, ...) \
syslog(LEVEL, __VA_ARGS__);
#define SYSLOGPRINT(LEVEL, ...) \
if(LEVEL <= LOG_CRIT || debug){ \
LOWSYSLOGPRINT(LEVEL, __VA_ARGS__); \
}
#define DPRINT(LEVEL, NEST, ...) \
FPRINT(NEST, __VA_ARGS__); \
SYSLOGPRINT(LEVEL, __VA_ARGS__);
#define DPRINT2(LEVEL, ...) \
FPRINT2(2, __VA_ARGS__); \
SYSLOGPRINT(LEVEL, __VA_ARGS__);
// print debug message
#define FPRN(...) FPRINT(0, __VA_ARGS__)
#define FPRNN(...) FPRINT(1, __VA_ARGS__)
#define FPRNNN(...) FPRINT(2, __VA_ARGS__)
#define FPRNINFO(...) FPRINT2(2, __VA_ARGS__)
// print debug message with putting syslog
#define DPRNCRIT(...) DPRINT(LOG_CRIT, 0, __VA_ARGS__)
#define DPRN(...) DPRINT(LOG_ERR, 0, __VA_ARGS__)
#define DPRNN(...) DPRINT(LOG_DEBUG, 1, __VA_ARGS__)
#define DPRNNN(...) DPRINT(LOG_DEBUG, 2, __VA_ARGS__)
#define DPRNINFO(...) DPRINT2(LOG_INFO, __VA_ARGS__)
//
// Typedef
//
typedef std::map<std::string, std::string> headers_t;
//
// Global valiables
//
extern bool debug;
extern bool foreground;
extern bool foreground2;
extern bool nomultipart;
extern bool pathrequeststyle;
extern std::string program_name;
extern std::string service_path;
extern std::string host;
extern std::string bucket;
extern std::string mount_prefix;
extern bool foreground;
extern bool nomultipart;
extern bool pathrequeststyle;
extern bool complement_stat;
extern bool noxmlns;
extern std::string program_name;
extern std::string service_path;
extern std::string s3host;
extern std::string bucket;
extern std::string mount_prefix;
extern std::string endpoint;
extern std::string cipher_suites;
extern std::string instance_name;
extern std::string aws_profile;
#endif // S3FS_COMMON_H_
@ -102,6 +56,6 @@ extern std::string mount_prefix;
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
* vim600: expandtab sw=4 ts=4 fdm=marker
* vim<600: expandtab sw=4 ts=4
*/

View File

@ -1,7 +1,7 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright 2007-2008 Randy Rizun <rrizun@gmail.com>
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -18,88 +18,54 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include "common.h"
#include "s3fs.h"
#include "s3fs_auth.h"
using namespace std;
#include "string_util.h"
//-------------------------------------------------------------------
// Utility Function
//-------------------------------------------------------------------
char* s3fs_base64(unsigned char* input, size_t length)
std::string s3fs_get_content_md5(int fd)
{
static const char* base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
char* result;
unsigned char* md5;
char* base64;
std::string Signature;
if(!input || 0 >= length){
return NULL;
}
if(NULL == (result = (char*)malloc((((length / 3) + 1) * 4 + 1) * sizeof(char)))){
return NULL; // ENOMEM
}
if(NULL == (md5 = s3fs_md5_fd(fd, 0, -1))){
return std::string("");
}
if(NULL == (base64 = s3fs_base64(md5, get_md5_digest_length()))){
delete[] md5;
return std::string(""); // ENOMEM
}
delete[] md5;
unsigned char parts[4];
size_t rpos;
size_t wpos;
for(rpos = 0, wpos = 0; rpos < length; rpos += 3){
parts[0] = (input[rpos] & 0xfc) >> 2;
parts[1] = ((input[rpos] & 0x03) << 4) | ((((rpos + 1) < length ? input[rpos + 1] : 0x00) & 0xf0) >> 4);
parts[2] = (rpos + 1) < length ? (((input[rpos + 1] & 0x0f) << 2) | ((((rpos + 2) < length ? input[rpos + 2] : 0x00) & 0xc0) >> 6)) : 0x40;
parts[3] = (rpos + 2) < length ? (input[rpos + 2] & 0x3f) : 0x40;
Signature = base64;
delete[] base64;
result[wpos++] = base[parts[0]];
result[wpos++] = base[parts[1]];
result[wpos++] = base[parts[2]];
result[wpos++] = base[parts[3]];
}
result[wpos] = '\0';
return result;
return Signature;
}
string s3fs_get_content_md5(int fd)
std::string s3fs_sha256_hex_fd(int fd, off_t start, off_t size)
{
unsigned char* md5hex;
char* base64;
string Signature;
size_t digestlen = get_sha256_digest_length();
unsigned char* sha256;
if(NULL == (md5hex = s3fs_md5hexsum(fd, 0, -1))){
return string("");
}
if(NULL == (base64 = s3fs_base64(md5hex, get_md5_digest_length()))){
return string(""); // ENOMEM
}
free(md5hex);
if(NULL == (sha256 = s3fs_sha256_fd(fd, start, size))){
return std::string("");
}
Signature = base64;
free(base64);
std::string sha256hex = s3fs_hex_lower(sha256, digestlen);
delete[] sha256;
return Signature;
}
string s3fs_md5sum(int fd, off_t start, ssize_t size)
{
size_t digestlen = get_md5_digest_length();
char md5[2 * digestlen + 1];
char hexbuf[3];
unsigned char* md5hex;
if(NULL == (md5hex = s3fs_md5hexsum(fd, start, size))){
return string("");
}
memset(md5, 0, 2 * digestlen + 1);
for(size_t pos = 0; pos < digestlen; pos++){
snprintf(hexbuf, 3, "%02x", md5hex[pos]);
strncat(md5, hexbuf, 2);
}
free(md5hex);
return string(md5);
return sha256hex;
}
/*
@ -107,6 +73,6 @@ string s3fs_md5sum(int fd, off_t start, ssize_t size)
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
* vim600: expandtab sw=4 ts=4 fdm=marker
* vim<600: expandtab sw=4 ts=4
*/

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright 2007-2008 Randy Rizun <rrizun@gmail.com>
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,412 +17,413 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef S3FS_CURL_H_
#define S3FS_CURL_H_
#include <cassert>
#include <curl/curl.h>
#include <list>
#include <map>
#include <strings.h>
#include <vector>
#include "common.h"
#include "curl_handlerpool.h"
#include "bodydata.h"
#include "psemaphore.h"
#include "metaheader.h"
#include "fdcache_page.h"
//----------------------------------------------
// class BodyData
// Avoid dependency on libcurl version
//----------------------------------------------
// memory class for curl write memory callback
// [NOTE]
// The following symbols (enum) depend on the version of libcurl.
// CURLOPT_TCP_KEEPALIVE 7.25.0 and later
// CURLOPT_SSL_ENABLE_ALPN 7.36.0 and later
// CURLOPT_KEEP_SENDING_ON_ERROR 7.51.0 and later
//
class BodyData
{
private:
char* text;
size_t lastpos;
size_t bufsize;
// s3fs uses these, if you build s3fs with the old libcurl,
// substitute the following symbols to avoid errors.
// If the version of libcurl linked at runtime is old,
// curl_easy_setopt results in an error(CURLE_UNKNOWN_OPTION) and
// a message is output.
//
#if defined(HAVE_CURLOPT_TCP_KEEPALIVE) && (HAVE_CURLOPT_TCP_KEEPALIVE == 1)
#define S3FS_CURLOPT_TCP_KEEPALIVE CURLOPT_TCP_KEEPALIVE
#else
#define S3FS_CURLOPT_TCP_KEEPALIVE static_cast<CURLoption>(213)
#endif
private:
bool IsSafeSize(size_t addbytes) const {
return ((lastpos + addbytes + 1) > bufsize ? false : true);
}
bool Resize(size_t addbytes);
#if defined(HAVE_CURLOPT_SSL_ENABLE_ALPN) && (HAVE_CURLOPT_SSL_ENABLE_ALPN == 1)
#define S3FS_CURLOPT_SSL_ENABLE_ALPN CURLOPT_SSL_ENABLE_ALPN
#else
#define S3FS_CURLOPT_SSL_ENABLE_ALPN static_cast<CURLoption>(226)
#endif
public:
BodyData() : text(NULL), lastpos(0), bufsize(0) {}
~BodyData() {
Clear();
}
void Clear(void);
bool Append(void* ptr, size_t bytes);
bool Append(void* ptr, size_t blockSize, size_t numBlocks) {
return Append(ptr, (blockSize * numBlocks));
}
const char* str() const;
size_t size() const {
return lastpos;
}
};
#if defined(HAVE_CURLOPT_KEEP_SENDING_ON_ERROR) && (HAVE_CURLOPT_KEEP_SENDING_ON_ERROR == 1)
#define S3FS_CURLOPT_KEEP_SENDING_ON_ERROR CURLOPT_KEEP_SENDING_ON_ERROR
#else
#define S3FS_CURLOPT_KEEP_SENDING_ON_ERROR static_cast<CURLoption>(245)
#endif
//----------------------------------------------
// Utility structs & typedefs
// Structure / Typedefs
//----------------------------------------------
typedef std::vector<std::string> etaglist_t;
// Each part information for Multipart upload
struct filepart
{
bool uploaded; // does finish uploading
std::string etag; // expected etag value
int fd; // base file(temporary full file) discriptor
off_t startpos; // seek fd point for uploading
ssize_t size; // uploading size
etaglist_t* etaglist; // use only parallel upload
int etagpos; // use only parallel upload
filepart() : uploaded(false), fd(-1), startpos(0), size(-1), etaglist(NULL), etagpos(-1) {}
~filepart()
{
clear();
}
void clear(void)
{
uploaded = false;
etag = "";
fd = -1;
startpos = 0;
size = -1;
etaglist = NULL;
etagpos = - 1;
}
void add_etag_list(etaglist_t* list)
{
if(list){
list->push_back(std::string(""));
etaglist = list;
etagpos = list->size() - 1;
}else{
etaglist = NULL;
etagpos = - 1;
}
}
};
// for progress
struct case_insensitive_compare_func
{
bool operator()(const std::string& a, const std::string& b) const {
return strcasecmp(a.c_str(), b.c_str()) < 0;
}
};
typedef std::map<std::string, std::string, case_insensitive_compare_func> mimes_t;
typedef std::pair<double, double> progress_t;
typedef std::map<CURL*, time_t> curltime_t;
typedef std::map<CURL*, progress_t> curlprogress_t;
class S3fsMultiCurl;
//----------------------------------------------
// class S3fsCurl
//----------------------------------------------
class S3fsCurl;
// Prototype function for lazy setup options for curl handle
typedef bool (*s3fscurl_lazy_setup)(S3fsCurl* s3fscurl);
typedef std::map<std::string, std::string> iamcredmap_t;
typedef std::map<std::string, std::string> sseckeymap_t;
typedef std::list<sseckeymap_t> sseckeylist_t;
// share
#define SHARE_MUTEX_DNS 0
#define SHARE_MUTEX_SSL_SESSION 1
#define SHARE_MUTEX_MAX 2
// Class for lapping curl
//
class S3fsCurl
{
friend class S3fsMultiCurl;
friend class S3fsMultiCurl;
private:
enum REQTYPE {
REQTYPE_UNSET = -1,
REQTYPE_DELETE = 0,
REQTYPE_HEAD,
REQTYPE_PUTHEAD,
REQTYPE_PUT,
REQTYPE_GET,
REQTYPE_CHKBUCKET,
REQTYPE_LISTBUCKET,
REQTYPE_PREMULTIPOST,
REQTYPE_COMPLETEMULTIPOST,
REQTYPE_UPLOADMULTIPOST,
REQTYPE_COPYMULTIPOST,
REQTYPE_MULTILIST,
REQTYPE_IAMCRED,
REQTYPE_ABORTMULTIUPLOAD
};
private:
enum REQTYPE {
REQTYPE_UNSET = -1,
REQTYPE_DELETE = 0,
REQTYPE_HEAD,
REQTYPE_PUTHEAD,
REQTYPE_PUT,
REQTYPE_GET,
REQTYPE_CHKBUCKET,
REQTYPE_LISTBUCKET,
REQTYPE_PREMULTIPOST,
REQTYPE_COMPLETEMULTIPOST,
REQTYPE_UPLOADMULTIPOST,
REQTYPE_COPYMULTIPOST,
REQTYPE_MULTILIST,
REQTYPE_IAMCRED,
REQTYPE_ABORTMULTIUPLOAD,
REQTYPE_IAMROLE
};
// class variables
static pthread_mutex_t curl_handles_lock;
static pthread_mutex_t curl_share_lock[SHARE_MUTEX_MAX];
static bool is_initglobal_done;
static CURLSH* hCurlShare;
static bool is_dns_cache;
static bool is_ssl_session_cache;
static long connect_timeout;
static time_t readwrite_timeout;
static int retries;
static bool is_public_bucket;
static std::string default_acl; // TODO: to enum
static bool is_use_rrs;
static sseckeylist_t sseckeys;
static bool is_use_sse;
static bool is_content_md5;
static bool is_verbose;
static std::string AWSAccessKeyId;
static std::string AWSSecretAccessKey;
static std::string AWSAccessToken;
static time_t AWSAccessTokenExpire;
static std::string IAM_role;
static long ssl_verify_hostname;
static curltime_t curl_times;
static curlprogress_t curl_progress;
static std::string curl_ca_bundle;
static mimes_t mimeTypes;
static int max_parallel_cnt;
static off_t multipart_size;
// class variables
static pthread_mutex_t curl_warnings_lock;
static bool curl_warnings_once; // emit older curl warnings only once
static pthread_mutex_t curl_handles_lock;
static struct callback_locks_t {
pthread_mutex_t dns;
pthread_mutex_t ssl_session;
} callback_locks;
static bool is_initglobal_done;
static CurlHandlerPool* sCurlPool;
static int sCurlPoolSize;
static CURLSH* hCurlShare;
static bool is_cert_check;
static bool is_dns_cache;
static bool is_ssl_session_cache;
static long connect_timeout;
static time_t readwrite_timeout;
static int retries;
static bool is_public_bucket;
static acl_t default_acl;
static std::string storage_class;
static sseckeylist_t sseckeys;
static std::string ssekmsid;
static sse_type_t ssetype;
static bool is_content_md5;
static bool is_verbose;
static bool is_dump_body;
static std::string AWSAccessKeyId;
static std::string AWSSecretAccessKey;
static std::string AWSAccessToken;
static time_t AWSAccessTokenExpire;
static bool is_ecs;
static bool is_use_session_token;
static bool is_ibm_iam_auth;
static std::string IAM_cred_url;
static int IAM_api_version;
static std::string IAMv2_token_url;
static int IAMv2_token_ttl;
static std::string IAMv2_token_ttl_hdr;
static std::string IAMv2_token_hdr;
static std::string IAMv2_api_token;
static size_t IAM_field_count;
static std::string IAM_token_field;
static std::string IAM_expiry_field;
static std::string IAM_role;
static long ssl_verify_hostname;
static curltime_t curl_times;
static curlprogress_t curl_progress;
static std::string curl_ca_bundle;
static mimes_t mimeTypes;
static std::string userAgent;
static int max_parallel_cnt;
static int max_multireq;
static off_t multipart_size;
static off_t multipart_copy_size;
static signature_type_t signature_type;
static bool is_ua; // User-Agent
static bool listobjectsv2;
static bool requester_pays;
// variables
CURL* hCurl;
REQTYPE type; // type of request
std::string path; // target object path
std::string base_path; // base path (for multi curl head request)
std::string saved_path; // saved path = cache key (for multi curl head request)
std::string url; // target object path(url)
struct curl_slist* requestHeaders;
headers_t responseHeaders; // header data by HeaderCallback
BodyData* bodydata; // body data by WriteMemoryCallback
BodyData* headdata; // header data by WriteMemoryCallback
long LastResponseCode;
const unsigned char* postdata; // use by post method and read callback function.
int postdata_remaining; // use by post method and read callback function.
filepart partdata; // use by multipart upload/get object callback
bool is_use_ahbe; // additional header by extension
int retry_count; // retry count for multipart
FILE* b_infile; // backup for retrying
const unsigned char* b_postdata; // backup for retrying
int b_postdata_remaining; // backup for retrying
off_t b_partdata_startpos; // backup for retrying
ssize_t b_partdata_size; // backup for retrying
bool b_ssekey_pos; // backup for retrying
std::string b_ssekey_md5; // backup for retrying
// variables
CURL* hCurl;
REQTYPE type; // type of request
std::string path; // target object path
std::string base_path; // base path (for multi curl head request)
std::string saved_path; // saved path = cache key (for multi curl head request)
std::string url; // target object path(url)
struct curl_slist* requestHeaders;
headers_t responseHeaders; // header data by HeaderCallback
BodyData bodydata; // body data by WriteMemoryCallback
BodyData headdata; // header data by WriteMemoryCallback
long LastResponseCode;
const unsigned char* postdata; // use by post method and read callback function.
off_t postdata_remaining; // use by post method and read callback function.
filepart partdata; // use by multipart upload/get object callback
bool is_use_ahbe; // additional header by extension
int retry_count; // retry count for multipart
FILE* b_infile; // backup for retrying
const unsigned char* b_postdata; // backup for retrying
off_t b_postdata_remaining; // backup for retrying
off_t b_partdata_startpos; // backup for retrying
off_t b_partdata_size; // backup for retrying
size_t b_ssekey_pos; // backup for retrying
std::string b_ssevalue; // backup for retrying
sse_type_t b_ssetype; // backup for retrying
std::string b_from; // backup for retrying(for copy request)
headers_t b_meta; // backup for retrying(for copy request)
std::string op; // the HTTP verb of the request ("PUT", "GET", etc.)
std::string query_string; // request query string
Semaphore *sem;
pthread_mutex_t *completed_tids_lock;
std::vector<pthread_t> *completed_tids;
s3fscurl_lazy_setup fpLazySetup; // curl options for lazy setting function
CURLcode curlCode; // handle curl return
public:
static const long S3FSCURL_RESPONSECODE_NOTSET = -1;
static const long S3FSCURL_RESPONSECODE_FATAL_ERROR = -2;
static const int S3FSCURL_PERFORM_RESULT_NOTSET = 1;
public:
// constructor/destructor
S3fsCurl(bool ahbe = false);
~S3fsCurl();
public:
// constructor/destructor
explicit S3fsCurl(bool ahbe = false);
~S3fsCurl();
private:
// class methods
static bool InitGlobalCurl(void);
static bool DestroyGlobalCurl(void);
static bool InitShareCurl(void);
static bool DestroyShareCurl(void);
static void LockCurlShare(CURL* handle, curl_lock_data nLockData, curl_lock_access laccess, void* useptr);
static void UnlockCurlShare(CURL* handle, curl_lock_data nLockData, void* useptr);
static bool InitCryptMutex(void);
static bool DestroyCryptMutex(void);
static int CurlProgress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);
private:
// class methods
static bool InitGlobalCurl();
static bool DestroyGlobalCurl();
static bool InitShareCurl();
static bool DestroyShareCurl();
static void LockCurlShare(CURL* handle, curl_lock_data nLockData, curl_lock_access laccess, void* useptr);
static void UnlockCurlShare(CURL* handle, curl_lock_data nLockData, void* useptr);
static bool InitCryptMutex();
static bool DestroyCryptMutex();
static int CurlProgress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow);
static bool InitMimeType(const char* MimeFile = NULL);
static bool LocateBundle(void);
static size_t HeaderCallback(void *data, size_t blockSize, size_t numBlocks, void *userPtr);
static size_t WriteMemoryCallback(void *ptr, size_t blockSize, size_t numBlocks, void *data);
static size_t ReadCallback(void *ptr, size_t size, size_t nmemb, void *userp);
static size_t UploadReadCallback(void *ptr, size_t size, size_t nmemb, void *userp);
static size_t DownloadWriteCallback(void* ptr, size_t size, size_t nmemb, void* userp);
static bool LocateBundle();
static size_t HeaderCallback(void *data, size_t blockSize, size_t numBlocks, void *userPtr);
static size_t WriteMemoryCallback(void *ptr, size_t blockSize, size_t numBlocks, void *data);
static size_t ReadCallback(void *ptr, size_t size, size_t nmemb, void *userp);
static size_t UploadReadCallback(void *ptr, size_t size, size_t nmemb, void *userp);
static size_t DownloadWriteCallback(void* ptr, size_t size, size_t nmemb, void* userp);
static bool UploadMultipartPostCallback(S3fsCurl* s3fscurl);
static S3fsCurl* UploadMultipartPostRetryCallback(S3fsCurl* s3fscurl);
static S3fsCurl* ParallelGetObjectRetryCallback(S3fsCurl* s3fscurl);
static bool UploadMultipartPostCallback(S3fsCurl* s3fscurl);
static bool CopyMultipartPostCallback(S3fsCurl* s3fscurl);
static bool MixMultipartPostCallback(S3fsCurl* s3fscurl);
static S3fsCurl* UploadMultipartPostRetryCallback(S3fsCurl* s3fscurl);
static S3fsCurl* CopyMultipartPostRetryCallback(S3fsCurl* s3fscurl);
static S3fsCurl* MixMultipartPostRetryCallback(S3fsCurl* s3fscurl);
static S3fsCurl* ParallelGetObjectRetryCallback(S3fsCurl* s3fscurl);
static bool ParseIAMCredentialResponse(const char* response, iamcredmap_t& keyval);
static bool SetIAMCredentials(const char* response);
static bool PushbackSseKeys(std::string& onekey);
// lazy functions for set curl options
static bool UploadMultipartPostSetCurlOpts(S3fsCurl* s3fscurl);
static bool CopyMultipartPostSetCurlOpts(S3fsCurl* s3fscurl);
static bool PreGetObjectRequestSetCurlOpts(S3fsCurl* s3fscurl);
static bool PreHeadRequestSetCurlOpts(S3fsCurl* s3fscurl);
// methods
bool ResetHandle(void);
bool RemakeHandle(void);
bool ClearInternalData(void);
std::string CalcSignature(std::string method, std::string strMD5, std::string content_type, std::string date, std::string resource);
bool GetUploadId(std::string& upload_id);
int GetIAMCredentials(void);
static bool ParseIAMCredentialResponse(const char* response, iamcredmap_t& keyval);
static bool SetIAMCredentials(const char* response);
static bool SetIAMv2APIToken(const char* response);
static bool ParseIAMRoleFromMetaDataResponse(const char* response, std::string& rolename);
static bool SetIAMRoleFromMetaData(const char* response);
static bool LoadEnvSseCKeys();
static bool LoadEnvSseKmsid();
static bool PushbackSseKeys(const std::string& onekey);
static bool AddUserAgent(CURL* hCurl);
int PreMultipartPostRequest(const char* tpath, headers_t& meta, std::string& upload_id, bool is_copy);
int CompleteMultipartPostRequest(const char* tpath, std::string& upload_id, etaglist_t& parts);
int UploadMultipartPostSetup(const char* tpath, int part_num, std::string& upload_id);
int UploadMultipartPostRequest(const char* tpath, int part_num, std::string& upload_id);
int CopyMultipartPostRequest(const char* from, const char* to, int part_num, std::string& upload_id, headers_t& meta);
static int CurlDebugFunc(CURL* hcurl, curl_infotype type, char* data, size_t size, void* userptr);
static int CurlDebugBodyInFunc(CURL* hcurl, curl_infotype type, char* data, size_t size, void* userptr);
static int CurlDebugBodyOutFunc(CURL* hcurl, curl_infotype type, char* data, size_t size, void* userptr);
static int RawCurlDebugFunc(CURL* hcurl, curl_infotype type, char* data, size_t size, void* userptr, curl_infotype datatype);
public:
// class methods
static bool InitS3fsCurl(const char* MimeFile = NULL);
static bool DestroyS3fsCurl(void);
static int ParallelMultipartUploadRequest(const char* tpath, headers_t& meta, int fd);
static int ParallelGetObjectRequest(const char* tpath, int fd, off_t start, ssize_t size);
static bool CheckIAMCredentialUpdate(void);
// methods
bool ResetHandle(bool lock_already_held = false);
bool RemakeHandle();
bool ClearInternalData();
void insertV4Headers();
void insertV2Headers();
void insertIBMIAMHeaders();
void insertAuthHeaders();
std::string CalcSignatureV2(const std::string& method, const std::string& strMD5, const std::string& content_type, const std::string& date, const std::string& resource);
std::string CalcSignature(const std::string& method, const std::string& canonical_uri, const std::string& query_string, const std::string& strdate, const std::string& payload_hash, const std::string& date8601);
int GetIAMv2ApiToken();
int GetIAMCredentials();
// class methods(valiables)
static std::string LookupMimeType(std::string name);
static bool SetDnsCache(bool isCache);
static bool SetSslSessionCache(bool isCache);
static long SetConnectTimeout(long timeout);
static time_t SetReadwriteTimeout(time_t timeout);
static time_t GetReadwriteTimeout(void) { return S3fsCurl::readwrite_timeout; }
static int SetRetries(int count);
static bool SetPublicBucket(bool flag);
static bool IsPublicBucket(void) { return S3fsCurl::is_public_bucket; }
static std::string SetDefaultAcl(const char* acl);
static bool SetUseRrs(bool flag);
static bool GetUseRrs(void) { return S3fsCurl::is_use_rrs; }
static bool SetSseKeys(const char* filepath);
static bool LoadEnvSseKeys(void);
static bool GetSseKey(std::string& md5, std::string& ssekey);
static bool GetSseKeyMd5(int pos, std::string& md5);
static int GetSseKeyCount(void);
static bool IsSseCustomMode(void);
static bool SetUseSse(bool flag);
static bool GetUseSse(void) { return S3fsCurl::is_use_sse; }
static bool SetContentMd5(bool flag);
static bool SetVerbose(bool flag);
static bool GetVerbose(void) { return S3fsCurl::is_verbose; }
static bool SetAccessKey(const char* AccessKeyId, const char* SecretAccessKey);
static bool IsSetAccessKeyId(void){
return (0 < S3fsCurl::IAM_role.size() || (0 < S3fsCurl::AWSAccessKeyId.size() && 0 < S3fsCurl::AWSSecretAccessKey.size()));
}
static long SetSslVerifyHostname(long value);
static long GetSslVerifyHostname(void) { return S3fsCurl::ssl_verify_hostname; }
static int SetMaxParallelCount(int value);
static int GetMaxParallelCount(void) { return S3fsCurl::max_parallel_cnt; }
static std::string SetIAMRole(const char* role);
static const char* GetIAMRole(void) { return S3fsCurl::IAM_role.c_str(); }
static bool SetMultipartSize(off_t size);
static off_t GetMultipartSize(void) { return S3fsCurl::multipart_size; }
int UploadMultipartPostSetup(const char* tpath, int part_num, const std::string& upload_id);
int CopyMultipartPostSetup(const char* from, const char* to, int part_num, const std::string& upload_id, headers_t& meta);
bool UploadMultipartPostComplete();
bool CopyMultipartPostComplete();
bool MixMultipartPostComplete();
int MapPutErrorResponse(int result);
// methods
bool CreateCurlHandle(bool force = false);
bool DestroyCurlHandle(void);
public:
// class methods
static bool InitS3fsCurl();
static bool InitMimeType(const std::string& strFile);
static bool DestroyS3fsCurl();
static int ParallelMultipartUploadRequest(const char* tpath, headers_t& meta, int fd);
static int ParallelMixMultipartUploadRequest(const char* tpath, headers_t& meta, int fd, const fdpage_list_t& mixuppages);
static int ParallelGetObjectRequest(const char* tpath, int fd, off_t start, off_t size);
static bool CheckIAMCredentialUpdate();
bool AddSseKeyRequestHead(std::string& md5, bool is_copy);
bool GetResponseCode(long& responseCode);
int RequestPerform(void);
int DeleteRequest(const char* tpath);
bool PreHeadRequest(const char* tpath, const char* bpath = NULL, const char* savedpath = NULL, int ssekey_pos = -1);
bool PreHeadRequest(std::string& tpath, std::string& bpath, std::string& savedpath, int ssekey_pos = -1) {
return PreHeadRequest(tpath.c_str(), bpath.c_str(), savedpath.c_str(), ssekey_pos);
}
int HeadRequest(const char* tpath, headers_t& meta);
int PutHeadRequest(const char* tpath, headers_t& meta, bool is_copy);
int PutRequest(const char* tpath, headers_t& meta, int fd);
int PreGetObjectRequest(const char* tpath, int fd, off_t start, ssize_t size, std::string& ssekeymd5);
int GetObjectRequest(const char* tpath, int fd, off_t start = -1, ssize_t size = -1);
int CheckBucket(void);
int ListBucketRequest(const char* tpath, const char* query);
int MultipartListRequest(std::string& body);
int AbortMultipartUpload(const char* tpath, std::string& upload_id);
int MultipartHeadRequest(const char* tpath, off_t size, headers_t& meta, bool is_copy);
int MultipartUploadRequest(const char* tpath, headers_t& meta, int fd, bool is_copy);
int MultipartRenameRequest(const char* from, const char* to, headers_t& meta, off_t size);
// class methods(variables)
static std::string LookupMimeType(const std::string& name);
static bool SetCheckCertificate(bool isCertCheck);
static bool SetDnsCache(bool isCache);
static bool SetSslSessionCache(bool isCache);
static long SetConnectTimeout(long timeout);
static time_t SetReadwriteTimeout(time_t timeout);
static time_t GetReadwriteTimeout() { return S3fsCurl::readwrite_timeout; }
static int SetRetries(int count);
static bool SetPublicBucket(bool flag);
static bool IsPublicBucket() { return S3fsCurl::is_public_bucket; }
static acl_t SetDefaultAcl(acl_t acl);
static acl_t GetDefaultAcl();
static std::string SetStorageClass(const std::string& storage_class);
static std::string GetStorageClass() { return S3fsCurl::storage_class; }
static bool LoadEnvSse() { return (S3fsCurl::LoadEnvSseCKeys() && S3fsCurl::LoadEnvSseKmsid()); }
static sse_type_t SetSseType(sse_type_t type);
static sse_type_t GetSseType() { return S3fsCurl::ssetype; }
static bool IsSseDisable() { return (sse_type_t::SSE_DISABLE == S3fsCurl::ssetype); }
static bool IsSseS3Type() { return (sse_type_t::SSE_S3 == S3fsCurl::ssetype); }
static bool IsSseCType() { return (sse_type_t::SSE_C == S3fsCurl::ssetype); }
static bool IsSseKmsType() { return (sse_type_t::SSE_KMS == S3fsCurl::ssetype); }
static bool FinalCheckSse();
static bool SetSseCKeys(const char* filepath);
static bool SetSseKmsid(const char* kmsid);
static bool IsSetSseKmsId() { return !S3fsCurl::ssekmsid.empty(); }
static const char* GetSseKmsId() { return S3fsCurl::ssekmsid.c_str(); }
static bool GetSseKey(std::string& md5, std::string& ssekey);
static bool GetSseKeyMd5(size_t pos, std::string& md5);
static size_t GetSseKeyCount();
static bool SetContentMd5(bool flag);
static bool SetVerbose(bool flag);
static bool GetVerbose() { return S3fsCurl::is_verbose; }
static bool SetDumpBody(bool flag);
static bool IsDumpBody() { return S3fsCurl::is_dump_body; }
static bool SetAccessKey(const char* AccessKeyId, const char* SecretAccessKey);
static bool SetAccessKeyWithSessionToken(const char* AccessKeyId, const char* SecretAccessKey, const char * SessionToken);
static bool IsSetAccessKeyID()
{
return !S3fsCurl::AWSAccessKeyId.empty();
}
static bool IsSetAccessKeys()
{
return !S3fsCurl::IAM_role.empty() || ((!S3fsCurl::AWSAccessKeyId.empty() || S3fsCurl::is_ibm_iam_auth) && !S3fsCurl::AWSSecretAccessKey.empty());
}
static long SetSslVerifyHostname(long value);
static long GetSslVerifyHostname() { return S3fsCurl::ssl_verify_hostname; }
static void ResetOffset(S3fsCurl* pCurl);
// maximum parallel GET and PUT requests
static int SetMaxParallelCount(int value);
static int GetMaxParallelCount() { return S3fsCurl::max_parallel_cnt; }
// maximum parallel HEAD requests
static int SetMaxMultiRequest(int max);
static int GetMaxMultiRequest() { return S3fsCurl::max_multireq; }
static bool SetIsECS(bool flag);
static bool SetIsIBMIAMAuth(bool flag);
static size_t SetIAMFieldCount(size_t field_count);
static std::string SetIAMCredentialsURL(const char* url);
static std::string SetIAMTokenField(const char* token_field);
static std::string SetIAMExpiryField(const char* expiry_field);
static std::string SetIAMRole(const char* role);
static const char* GetIAMRole() { return S3fsCurl::IAM_role.c_str(); }
static bool SetMultipartSize(off_t size);
static off_t GetMultipartSize() { return S3fsCurl::multipart_size; }
static bool SetMultipartCopySize(off_t size);
static off_t GetMultipartCopySize() { return S3fsCurl::multipart_copy_size; }
static signature_type_t SetSignatureType(signature_type_t signature_type) { signature_type_t bresult = S3fsCurl::signature_type; S3fsCurl::signature_type = signature_type; return bresult; }
static signature_type_t GetSignatureType() { return S3fsCurl::signature_type; }
static bool SetUserAgentFlag(bool isset) { bool bresult = S3fsCurl::is_ua; S3fsCurl::is_ua = isset; return bresult; }
static bool IsUserAgentFlag() { return S3fsCurl::is_ua; }
static void InitUserAgent();
static bool SetListObjectsV2(bool isset) { bool bresult = S3fsCurl::listobjectsv2; S3fsCurl::listobjectsv2 = isset; return bresult; }
static bool IsListObjectsV2() { return S3fsCurl::listobjectsv2; }
static bool SetRequesterPays(bool flag) { bool old_flag = S3fsCurl::requester_pays; S3fsCurl::requester_pays = flag; return old_flag; }
static bool IsRequesterPays() { return S3fsCurl::requester_pays; }
static bool SetIMDSVersion(int version);
// methods(valiables)
CURL* GetCurlHandle(void) const { return hCurl; }
std::string GetPath(void) const { return path; }
std::string GetBasePath(void) const { return base_path; }
std::string GetSpacialSavedPath(void) const { return saved_path; }
std::string GetUrl(void) const { return url; }
headers_t* GetResponseHeaders(void) { return &responseHeaders; }
BodyData* GetBodyData(void) const { return bodydata; }
BodyData* GetHeadData(void) const { return headdata; }
long GetLastResponseCode(void) const { return LastResponseCode; }
bool SetUseAhbe(bool ahbe);
bool EnableUseAhbe(void) { return SetUseAhbe(true); }
bool DisableUseAhbe(void) { return SetUseAhbe(false); }
bool IsUseAhbe(void) const { return is_use_ahbe; }
int GetMultipartRetryCount(void) const { return retry_count; }
void SetMultipartRetryCount(int retrycnt) { retry_count = retrycnt; }
bool IsOverMultipartRetryCount(void) const { return (retry_count >= S3fsCurl::retries); }
int GetLastPreHeadSeecKeyPos(void) const { return b_ssekey_pos; }
// methods
bool CreateCurlHandle(bool only_pool = false, bool remake = false);
bool DestroyCurlHandle(bool restore_pool = true, bool clear_internal_data = true);
bool LoadIAMRoleFromMetaData();
bool AddSseRequestHead(sse_type_t ssetype, const std::string& ssevalue, bool is_only_c, bool is_copy);
bool GetResponseCode(long& responseCode, bool from_curl_handle = true);
int RequestPerform(bool dontAddAuthHeaders=false);
int DeleteRequest(const char* tpath);
bool PreHeadRequest(const char* tpath, const char* bpath = NULL, const char* savedpath = NULL, size_t ssekey_pos = -1);
bool PreHeadRequest(const std::string& tpath, const std::string& bpath, const std::string& savedpath, size_t ssekey_pos = -1) {
return PreHeadRequest(tpath.c_str(), bpath.c_str(), savedpath.c_str(), ssekey_pos);
}
int HeadRequest(const char* tpath, headers_t& meta);
int PutHeadRequest(const char* tpath, headers_t& meta, bool is_copy);
int PutRequest(const char* tpath, headers_t& meta, int fd);
int PreGetObjectRequest(const char* tpath, int fd, off_t start, off_t size, sse_type_t ssetype, const std::string& ssevalue);
int GetObjectRequest(const char* tpath, int fd, off_t start = -1, off_t size = -1);
int CheckBucket();
int ListBucketRequest(const char* tpath, const char* query);
int PreMultipartPostRequest(const char* tpath, headers_t& meta, std::string& upload_id, bool is_copy);
int CompleteMultipartPostRequest(const char* tpath, const std::string& upload_id, etaglist_t& parts);
int UploadMultipartPostRequest(const char* tpath, int part_num, const std::string& upload_id);
int MultipartListRequest(std::string& body);
int AbortMultipartUpload(const char* tpath, const std::string& upload_id);
int MultipartHeadRequest(const char* tpath, off_t size, headers_t& meta, bool is_copy);
int MultipartUploadRequest(const std::string& upload_id, const char* tpath, int fd, off_t offset, off_t size, int part_num, std::string* petag);
int MultipartRenameRequest(const char* from, const char* to, headers_t& meta, off_t size);
// methods(variables)
CURL* GetCurlHandle() const { return hCurl; }
std::string GetPath() const { return path; }
std::string GetBasePath() const { return base_path; }
std::string GetSpecialSavedPath() const { return saved_path; }
std::string GetUrl() const { return url; }
std::string GetOp() const { return op; }
headers_t* GetResponseHeaders() { return &responseHeaders; }
BodyData* GetBodyData() { return &bodydata; }
BodyData* GetHeadData() { return &headdata; }
CURLcode GetCurlCode() const { return curlCode; }
long GetLastResponseCode() const { return LastResponseCode; }
bool SetUseAhbe(bool ahbe);
bool EnableUseAhbe() { return SetUseAhbe(true); }
bool DisableUseAhbe() { return SetUseAhbe(false); }
bool IsUseAhbe() const { return is_use_ahbe; }
int GetMultipartRetryCount() const { return retry_count; }
void SetMultipartRetryCount(int retrycnt) { retry_count = retrycnt; }
bool IsOverMultipartRetryCount() const { return (retry_count >= S3fsCurl::retries); }
size_t GetLastPreHeadSeecKeyPos() const { return b_ssekey_pos; }
};
//----------------------------------------------
// class S3fsMultiCurl
//----------------------------------------------
// Class for lapping multi curl
//
typedef std::map<CURL*, S3fsCurl*> s3fscurlmap_t;
typedef bool (*S3fsMultiSuccessCallback)(S3fsCurl* s3fscurl); // callback for succeed multi request
typedef S3fsCurl* (*S3fsMultiRetryCallback)(S3fsCurl* s3fscurl); // callback for failuer and retrying
class S3fsMultiCurl
{
private:
static int max_multireq;
CURLM* hMulti;
s3fscurlmap_t cMap_all; // all of curl requests
s3fscurlmap_t cMap_req; // curl requests are sent
S3fsMultiSuccessCallback SuccessCallback;
S3fsMultiRetryCallback RetryCallback;
private:
bool ClearEx(bool is_all);
int MultiPerform(void);
int MultiRead(void);
public:
S3fsMultiCurl();
~S3fsMultiCurl();
static int SetMaxMultiRequest(int max);
static int GetMaxMultiRequest(void) { return S3fsMultiCurl::max_multireq; }
S3fsMultiSuccessCallback SetSuccessCallback(S3fsMultiSuccessCallback function);
S3fsMultiRetryCallback SetRetryCallback(S3fsMultiRetryCallback function);
bool Clear(void) { return ClearEx(true); }
bool SetS3fsCurlObject(S3fsCurl* s3fscurl);
int Request(void);
};
//----------------------------------------------
// class AdditionalHeader
//----------------------------------------------
typedef std::list<int> charcnt_list_t;
typedef std::map<std::string, std::string> headerpair_t;
typedef std::map<std::string, headerpair_t> addheader_t;
class AdditionalHeader
{
private:
static AdditionalHeader singleton;
bool is_enable;
charcnt_list_t charcntlist;
addheader_t addheader;
public:
// Reference singleton
static AdditionalHeader* get(void) { return &singleton; }
AdditionalHeader();
~AdditionalHeader();
bool Load(const char* file);
void Unload(void);
bool AddHeader(headers_t& meta, const char* path) const;
struct curl_slist* AddHeader(struct curl_slist* list, const char* path) const;
bool Dump(void) const;
};
//----------------------------------------------
// Utility Functions
//----------------------------------------------
std::string GetContentMD5(int fd);
unsigned char* md5hexsum(int fd, off_t start, ssize_t size);
std::string md5sum(int fd, off_t start, ssize_t size);
struct curl_slist* curl_slist_sort_insert(struct curl_slist* list, const char* data);
bool MakeUrlResource(const char* realpath, std::string& resourcepath, std::string& url);
#endif // S3FS_CURL_H_
/*
@ -430,6 +431,6 @@ bool MakeUrlResource(const char* realpath, std::string& resourcepath, std::strin
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
* vim600: expandtab sw=4 ts=4 fdm=marker
* vim<600: expandtab sw=4 ts=4
*/

127
src/curl_handlerpool.cpp Normal file
View File

@ -0,0 +1,127 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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 <cstdio>
#include <cstdlib>
#include "common.h"
#include "s3fs.h"
#include "curl_handlerpool.h"
#include "autolock.h"
//-------------------------------------------------------------------
// Class CurlHandlerPool
//-------------------------------------------------------------------
bool CurlHandlerPool::Init()
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
#if S3FS_PTHREAD_ERRORCHECK
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
#endif
if (0 != pthread_mutex_init(&mLock, &attr)) {
S3FS_PRN_ERR("Init curl handlers lock failed");
return false;
}
for(int cnt = 0; cnt < mMaxHandlers; ++cnt){
CURL* hCurl = curl_easy_init();
if(!hCurl){
S3FS_PRN_ERR("Init curl handlers pool failed");
Destroy();
return false;
}
mPool.push_back(hCurl);
}
return true;
}
bool CurlHandlerPool::Destroy()
{
while(!mPool.empty()){
CURL* hCurl = mPool.back();
mPool.pop_back();
if(hCurl){
curl_easy_cleanup(hCurl);
}
}
if (0 != pthread_mutex_destroy(&mLock)) {
S3FS_PRN_ERR("Destroy curl handlers lock failed");
return false;
}
return true;
}
CURL* CurlHandlerPool::GetHandler(bool only_pool)
{
CURL* hCurl = NULL;
{
AutoLock lock(&mLock);
if(!mPool.empty()){
hCurl = mPool.back();
mPool.pop_back();
S3FS_PRN_DBG("Get handler from pool: rest = %d", static_cast<int>(mPool.size()));
}
}
if(only_pool){
return hCurl;
}
if(!hCurl){
S3FS_PRN_INFO("Pool empty: force to create new handler");
hCurl = curl_easy_init();
}
return hCurl;
}
void CurlHandlerPool::ReturnHandler(CURL* hCurl, bool restore_pool)
{
if(!hCurl){
return;
}
if(restore_pool){
AutoLock lock(&mLock);
S3FS_PRN_DBG("Return handler to pool");
mPool.push_back(hCurl);
while(mMaxHandlers <= static_cast<int>(mPool.size())){
CURL* hOldCurl = mPool.front();
mPool.pop_front();
if(hOldCurl){
S3FS_PRN_INFO("Pool full: destroy the oldest handler");
curl_easy_cleanup(hOldCurl);
}
}
}else{
S3FS_PRN_INFO("Pool full: destroy the handler");
curl_easy_cleanup(hCurl);
}
}
/*
* 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
*/

64
src/curl_handlerpool.h Normal file
View File

@ -0,0 +1,64 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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.
*/
#ifndef S3FS_CURL_HANDLERPOOL_H_
#define S3FS_CURL_HANDLERPOOL_H_
#include <cassert>
#include <curl/curl.h>
//----------------------------------------------
// Typedefs
//----------------------------------------------
typedef std::list<CURL*> hcurllist_t;
//----------------------------------------------
// class CurlHandlerPool
//----------------------------------------------
class CurlHandlerPool
{
public:
explicit CurlHandlerPool(int maxHandlers) : mMaxHandlers(maxHandlers)
{
assert(maxHandlers > 0);
}
bool Init();
bool Destroy();
CURL* GetHandler(bool only_pool);
void ReturnHandler(CURL* hCurl, bool restore_pool);
private:
int mMaxHandlers;
pthread_mutex_t mLock;
hcurllist_t mPool;
};
#endif // S3FS_CURL_HANDLERPOOL_H_
/*
* 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
*/

368
src/curl_multi.cpp Normal file
View File

@ -0,0 +1,368 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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 <cstdio>
#include <cstdlib>
#include <cerrno>
#include "common.h"
#include "s3fs.h"
#include "curl_multi.h"
#include "curl.h"
#include "autolock.h"
//-------------------------------------------------------------------
// Class S3fsMultiCurl
//-------------------------------------------------------------------
S3fsMultiCurl::S3fsMultiCurl(int maxParallelism) : maxParallelism(maxParallelism), SuccessCallback(NULL), RetryCallback(NULL)
{
int result;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
#if S3FS_PTHREAD_ERRORCHECK
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
#endif
if (0 != (result = pthread_mutex_init(&completed_tids_lock, &attr))) {
S3FS_PRN_ERR("could not initialize completed_tids_lock: %i", result);
abort();
}
}
S3fsMultiCurl::~S3fsMultiCurl()
{
Clear();
int result;
if(0 != (result = pthread_mutex_destroy(&completed_tids_lock))){
S3FS_PRN_ERR("could not destroy completed_tids_lock: %i", result);
}
}
bool S3fsMultiCurl::ClearEx(bool is_all)
{
s3fscurllist_t::iterator iter;
for(iter = clist_req.begin(); iter != clist_req.end(); ++iter){
S3fsCurl* s3fscurl = *iter;
if(s3fscurl){
s3fscurl->DestroyCurlHandle();
delete s3fscurl; // with destroy curl handle.
}
}
clist_req.clear();
if(is_all){
for(iter = clist_all.begin(); iter != clist_all.end(); ++iter){
S3fsCurl* s3fscurl = *iter;
s3fscurl->DestroyCurlHandle();
delete s3fscurl;
}
clist_all.clear();
}
S3FS_MALLOCTRIM(0);
return true;
}
S3fsMultiSuccessCallback S3fsMultiCurl::SetSuccessCallback(S3fsMultiSuccessCallback function)
{
S3fsMultiSuccessCallback old = SuccessCallback;
SuccessCallback = function;
return old;
}
S3fsMultiRetryCallback S3fsMultiCurl::SetRetryCallback(S3fsMultiRetryCallback function)
{
S3fsMultiRetryCallback old = RetryCallback;
RetryCallback = function;
return old;
}
bool S3fsMultiCurl::SetS3fsCurlObject(S3fsCurl* s3fscurl)
{
if(!s3fscurl){
return false;
}
clist_all.push_back(s3fscurl);
return true;
}
int S3fsMultiCurl::MultiPerform()
{
std::vector<pthread_t> threads;
bool success = true;
bool isMultiHead = false;
Semaphore sem(GetMaxParallelism());
int rc;
for(s3fscurllist_t::iterator iter = clist_req.begin(); iter != clist_req.end(); ++iter) {
pthread_t thread;
S3fsCurl* s3fscurl = *iter;
if(!s3fscurl){
continue;
}
sem.wait();
{
AutoLock lock(&completed_tids_lock);
for(std::vector<pthread_t>::iterator it = completed_tids.begin(); it != completed_tids.end(); ++it){
void* retval;
rc = pthread_join(*it, &retval);
if (rc) {
success = false;
S3FS_PRN_ERR("failed pthread_join - rc(%d) %s", rc, strerror(rc));
} else {
int int_retval = (int)(intptr_t)(retval);
if (int_retval && !(int_retval == -ENOENT && isMultiHead)) {
S3FS_PRN_WARN("thread terminated with non-zero return code: %d", int_retval);
}
}
}
completed_tids.clear();
}
s3fscurl->sem = &sem;
s3fscurl->completed_tids_lock = &completed_tids_lock;
s3fscurl->completed_tids = &completed_tids;
isMultiHead |= s3fscurl->GetOp() == "HEAD";
rc = pthread_create(&thread, NULL, S3fsMultiCurl::RequestPerformWrapper, static_cast<void*>(s3fscurl));
if (rc != 0) {
success = false;
S3FS_PRN_ERR("failed pthread_create - rc(%d)", rc);
break;
}
threads.push_back(thread);
}
for(int i = 0; i < sem.get_value(); ++i){
sem.wait();
}
AutoLock lock(&completed_tids_lock);
for (std::vector<pthread_t>::iterator titer = completed_tids.begin(); titer != completed_tids.end(); ++titer) {
void* retval;
rc = pthread_join(*titer, &retval);
if (rc) {
success = false;
S3FS_PRN_ERR("failed pthread_join - rc(%d)", rc);
} else {
int int_retval = (int)(intptr_t)(retval);
if (int_retval && !(int_retval == -ENOENT && isMultiHead)) {
S3FS_PRN_WARN("thread terminated with non-zero return code: %d", int_retval);
}
}
}
completed_tids.clear();
return success ? 0 : -EIO;
}
int S3fsMultiCurl::MultiRead()
{
int result = 0;
for(s3fscurllist_t::iterator iter = clist_req.begin(); iter != clist_req.end(); ){
S3fsCurl* s3fscurl = *iter;
bool isRetry = false;
bool isPostpone = false;
bool isNeedResetOffset = true;
long responseCode = S3fsCurl::S3FSCURL_RESPONSECODE_NOTSET;
CURLcode curlCode = s3fscurl->GetCurlCode();
if(s3fscurl->GetResponseCode(responseCode, false) && curlCode == CURLE_OK){
if(S3fsCurl::S3FSCURL_RESPONSECODE_NOTSET == responseCode){
// This is a case where the processing result has not yet been updated (should be very rare).
isPostpone = true;
}else if(400 > responseCode){
// add into stat cache
if(SuccessCallback && !SuccessCallback(s3fscurl)){
S3FS_PRN_WARN("error from callback function(%s).", s3fscurl->url.c_str());
}
}else if(400 == responseCode){
// as possibly in multipart
S3FS_PRN_WARN("failed a request(%ld: %s)", responseCode, s3fscurl->url.c_str());
isRetry = true;
}else if(404 == responseCode){
// not found
// HEAD requests on readdir_multi_head can return 404
if(s3fscurl->GetOp() != "HEAD"){
S3FS_PRN_WARN("failed a request(%ld: %s)", responseCode, s3fscurl->url.c_str());
}
}else if(500 == responseCode){
// case of all other result, do retry.(11/13/2013)
// because it was found that s3fs got 500 error from S3, but could success
// to retry it.
S3FS_PRN_WARN("failed a request(%ld: %s)", responseCode, s3fscurl->url.c_str());
isRetry = true;
}else{
// Retry in other case.
S3FS_PRN_WARN("failed a request(%ld: %s)", responseCode, s3fscurl->url.c_str());
isRetry = true;
}
}else{
S3FS_PRN_ERR("failed a request(Unknown response code: %s)", s3fscurl->url.c_str());
// Reuse partical file
switch(curlCode){
case CURLE_OPERATION_TIMEDOUT:
isRetry = true;
isNeedResetOffset = false;
break;
case CURLE_PARTIAL_FILE:
isRetry = true;
isNeedResetOffset = false;
break;
default:
S3FS_PRN_ERR("###curlCode: %d msg: %s", curlCode, curl_easy_strerror(curlCode));
isRetry = true;
break;
}
}
if(isPostpone){
clist_req.erase(iter);
clist_req.push_back(s3fscurl); // Re-evaluate at the end
iter = clist_req.begin();
}else{
if(!isRetry || 0 != result){
// If an EIO error has already occurred, it will be terminated
// immediately even if retry processing is required.
s3fscurl->DestroyCurlHandle();
delete s3fscurl;
}else{
S3fsCurl* retrycurl = NULL;
// Reset offset
if(isNeedResetOffset){
S3fsCurl::ResetOffset(s3fscurl);
}
// For retry
if(RetryCallback){
retrycurl = RetryCallback(s3fscurl);
if(NULL != retrycurl){
clist_all.push_back(retrycurl);
}else{
// set EIO and wait for other parts.
result = -EIO;
}
}
if(s3fscurl != retrycurl){
s3fscurl->DestroyCurlHandle();
delete s3fscurl;
}
}
iter = clist_req.erase(iter);
}
}
clist_req.clear();
if(0 != result){
// If an EIO error has already occurred, clear all retry objects.
for(s3fscurllist_t::iterator iter = clist_all.begin(); iter != clist_all.end(); ++iter){
S3fsCurl* s3fscurl = *iter;
s3fscurl->DestroyCurlHandle();
delete s3fscurl;
}
clist_all.clear();
}
return result;
}
int S3fsMultiCurl::Request()
{
S3FS_PRN_INFO3("[count=%zu]", clist_all.size());
// Make request list.
//
// Send multi request loop( with retry )
// (When many request is sends, sometimes gets "Couldn't connect to server")
//
while(!clist_all.empty()){
// set curl handle to multi handle
int result;
s3fscurllist_t::iterator iter;
for(iter = clist_all.begin(); iter != clist_all.end(); ++iter){
S3fsCurl* s3fscurl = *iter;
clist_req.push_back(s3fscurl);
}
clist_all.clear();
// Send multi request.
if(0 != (result = MultiPerform())){
Clear();
return result;
}
// Read the result
if(0 != (result = MultiRead())){
Clear();
return result;
}
// Cleanup curl handle in multi handle
ClearEx(false);
}
return 0;
}
//
// thread function for performing an S3fsCurl request
//
void* S3fsMultiCurl::RequestPerformWrapper(void* arg)
{
S3fsCurl* s3fscurl= static_cast<S3fsCurl*>(arg);
void* result = NULL;
if(!s3fscurl){
return (void*)(intptr_t)(-EIO);
}
if(s3fscurl->fpLazySetup){
if(!s3fscurl->fpLazySetup(s3fscurl)){
S3FS_PRN_ERR("Failed to lazy setup, then respond EIO.");
result = (void*)(intptr_t)(-EIO);
}
}
if(!result){
result = (void*)(intptr_t)(s3fscurl->RequestPerform());
s3fscurl->DestroyCurlHandle(true, false);
}
AutoLock lock(s3fscurl->completed_tids_lock);
s3fscurl->completed_tids->push_back(pthread_self());
s3fscurl->sem->post();
return result;
}
/*
* 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
*/

79
src/curl_multi.h Normal file
View File

@ -0,0 +1,79 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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.
*/
#ifndef S3FS_CURL_MULTI_H_
#define S3FS_CURL_MULTI_H_
//----------------------------------------------
// Typedef
//----------------------------------------------
class S3fsCurl;
typedef std::vector<S3fsCurl*> s3fscurllist_t;
typedef bool (*S3fsMultiSuccessCallback)(S3fsCurl* s3fscurl); // callback for succeed multi request
typedef S3fsCurl* (*S3fsMultiRetryCallback)(S3fsCurl* s3fscurl); // callback for failure and retrying
//----------------------------------------------
// class S3fsMultiCurl
//----------------------------------------------
class S3fsMultiCurl
{
private:
const int maxParallelism;
s3fscurllist_t clist_all; // all of curl requests
s3fscurllist_t clist_req; // curl requests are sent
S3fsMultiSuccessCallback SuccessCallback;
S3fsMultiRetryCallback RetryCallback;
pthread_mutex_t completed_tids_lock;
std::vector<pthread_t> completed_tids;
private:
bool ClearEx(bool is_all);
int MultiPerform();
int MultiRead();
static void* RequestPerformWrapper(void* arg);
public:
explicit S3fsMultiCurl(int maxParallelism);
~S3fsMultiCurl();
int GetMaxParallelism() { return maxParallelism; }
S3fsMultiSuccessCallback SetSuccessCallback(S3fsMultiSuccessCallback function);
S3fsMultiRetryCallback SetRetryCallback(S3fsMultiRetryCallback function);
bool Clear() { return ClearEx(true); }
bool SetS3fsCurlObject(S3fsCurl* s3fscurl);
int Request();
};
#endif // S3FS_CURL_MULTI_H_
/*
* 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
*/

408
src/curl_util.cpp Normal file
View File

@ -0,0 +1,408 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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 <cstdio>
#include <cstdlib>
#include <curl/curl.h>
#include "common.h"
#include "s3fs.h"
#include "curl_util.h"
#include "string_util.h"
#include "s3fs_auth.h"
//-------------------------------------------------------------------
// Utility Functions
//-------------------------------------------------------------------
//
// curl_slist_sort_insert
// This function is like curl_slist_append function, but this adds data by a-sorting.
// Because AWS signature needs sorted header.
//
struct curl_slist* curl_slist_sort_insert(struct curl_slist* list, const char* data)
{
if(!data){
return list;
}
std::string strkey = data;
std::string strval;
std::string::size_type pos = strkey.find(':', 0);
if(std::string::npos != pos){
strval = strkey.substr(pos + 1);
strkey.erase(pos);
}
return curl_slist_sort_insert(list, strkey.c_str(), strval.c_str());
}
struct curl_slist* curl_slist_sort_insert(struct curl_slist* list, const char* key, const char* value)
{
if(!key){
return list;
}
// key & value are trimmed and lower (only key)
std::string strkey = trim(std::string(key));
std::string strval = value ? trim(std::string(value)) : "";
std::string strnew = key + std::string(": ") + strval;
char* data;
if(NULL == (data = strdup(strnew.c_str()))){
return list;
}
struct curl_slist **p = &list;
for(;*p; p = &(*p)->next){
std::string strcur = (*p)->data;
size_t pos;
if(std::string::npos != (pos = strcur.find(':', 0))){
strcur.erase(pos);
}
int result = strcasecmp(strkey.c_str(), strcur.c_str());
if(0 == result){
free((*p)->data);
(*p)->data = data;
return list;
}else if(result < 0){
break;
}
}
struct curl_slist* new_item;
if(NULL == (new_item = static_cast<struct curl_slist*>(malloc(sizeof(*new_item))))){
free(data);
return list;
}
struct curl_slist* before = *p;
*p = new_item;
new_item->data = data;
new_item->next = before;
return list;
}
struct curl_slist* curl_slist_remove(struct curl_slist* list, const char* key)
{
if(!key){
return list;
}
std::string strkey = trim(std::string(key));
struct curl_slist **p = &list;
for(;*p; p = &(*p)->next){
std::string strcur = (*p)->data;
size_t pos;
if(std::string::npos != (pos = strcur.find(':', 0))){
strcur.erase(pos);
}
int result = strcasecmp(strkey.c_str(), strcur.c_str());
if(0 == result){
free((*p)->data);
struct curl_slist *tmp = *p;
*p = (*p)->next;
free(tmp);
}
}
return list;
}
std::string get_sorted_header_keys(const struct curl_slist* list)
{
std::string sorted_headers;
if(!list){
return sorted_headers;
}
for( ; list; list = list->next){
std::string strkey = list->data;
size_t pos;
if(std::string::npos != (pos = strkey.find(':', 0))){
if (trim(strkey.substr(pos + 1)).empty()) {
// skip empty-value headers (as they are discarded by libcurl)
continue;
}
strkey.erase(pos);
}
if(!sorted_headers.empty()){
sorted_headers += ";";
}
sorted_headers += lower(strkey);
}
return sorted_headers;
}
std::string get_header_value(const struct curl_slist* list, const std::string &key)
{
if(!list){
return "";
}
for( ; list; list = list->next){
std::string strkey = list->data;
size_t pos;
if(std::string::npos != (pos = strkey.find(':', 0))){
if(0 == strcasecmp(trim(strkey.substr(0, pos)).c_str(), key.c_str())){
return trim(strkey.substr(pos+1));
}
}
}
return "";
}
std::string get_canonical_headers(const struct curl_slist* list)
{
std::string canonical_headers;
if(!list){
canonical_headers = "\n";
return canonical_headers;
}
for( ; list; list = list->next){
std::string strhead = list->data;
size_t pos;
if(std::string::npos != (pos = strhead.find(':', 0))){
std::string strkey = trim(lower(strhead.substr(0, pos)));
std::string strval = trim(strhead.substr(pos + 1));
if (strval.empty()) {
// skip empty-value headers (as they are discarded by libcurl)
continue;
}
strhead = strkey;
strhead += ":";
strhead += strval;
}else{
strhead = trim(lower(strhead));
}
canonical_headers += strhead;
canonical_headers += "\n";
}
return canonical_headers;
}
std::string get_canonical_headers(const struct curl_slist* list, bool only_amz)
{
std::string canonical_headers;
if(!list){
canonical_headers = "\n";
return canonical_headers;
}
for( ; list; list = list->next){
std::string strhead = list->data;
size_t pos;
if(std::string::npos != (pos = strhead.find(':', 0))){
std::string strkey = trim(lower(strhead.substr(0, pos)));
std::string strval = trim(strhead.substr(pos + 1));
if (strval.empty()) {
// skip empty-value headers (as they are discarded by libcurl)
continue;
}
strhead = strkey;
strhead += ":";
strhead += strval;
}else{
strhead = trim(lower(strhead));
}
if(only_amz && strhead.substr(0, 5) != "x-amz"){
continue;
}
canonical_headers += strhead;
canonical_headers += "\n";
}
return canonical_headers;
}
// function for using global values
bool MakeUrlResource(const char* realpath, std::string& resourcepath, std::string& url)
{
if(!realpath){
return false;
}
resourcepath = urlEncode(service_path + bucket + realpath);
url = s3host + resourcepath;
return true;
}
std::string prepare_url(const char* url)
{
S3FS_PRN_INFO3("URL is %s", url);
std::string uri;
std::string hostname;
std::string path;
std::string url_str = std::string(url);
std::string token = std::string("/") + bucket;
size_t bucket_pos;
size_t bucket_length = token.size();
size_t uri_length = 0;
if(!strncasecmp(url_str.c_str(), "https://", 8)){
uri_length = 8;
} else if(!strncasecmp(url_str.c_str(), "http://", 7)) {
uri_length = 7;
}
uri = url_str.substr(0, uri_length);
bucket_pos = url_str.find(token, uri_length);
if(!pathrequeststyle){
hostname = bucket + "." + url_str.substr(uri_length, bucket_pos - uri_length);
path = url_str.substr((bucket_pos + bucket_length));
}else{
hostname = url_str.substr(uri_length, bucket_pos - uri_length);
std::string part = url_str.substr((bucket_pos + bucket_length));
if('/' != part[0]){
part = "/" + part;
}
path = "/" + bucket + part;
}
url_str = uri + hostname + path;
S3FS_PRN_INFO3("URL changed is %s", url_str.c_str());
return url_str;
}
// [TODO]
// This function uses temporary file, but should not use it.
// For not using it, we implement function in each auth file(openssl, nss. gnutls).
//
bool make_md5_from_binary(const char* pstr, size_t length, std::string& md5)
{
if(!pstr || '\0' == pstr[0]){
S3FS_PRN_ERR("Parameter is wrong.");
return false;
}
FILE* fp;
if(NULL == (fp = tmpfile())){
S3FS_PRN_ERR("Could not make tmpfile.");
return false;
}
if(length != fwrite(pstr, sizeof(char), length, fp)){
S3FS_PRN_ERR("Failed to write tmpfile.");
fclose(fp);
return false;
}
int fd;
if(0 != fflush(fp) || 0 != fseek(fp, 0L, SEEK_SET) || -1 == (fd = fileno(fp))){
S3FS_PRN_ERR("Failed to make MD5.");
fclose(fp);
return false;
}
// base64 md5
md5 = s3fs_get_content_md5(fd);
if(md5.empty()){
S3FS_PRN_ERR("Failed to make MD5.");
fclose(fp);
return false;
}
fclose(fp);
return true;
}
std::string url_to_host(const std::string &url)
{
S3FS_PRN_INFO3("url is %s", url.c_str());
static const char HTTP[] = "http://";
static const char HTTPS[] = "https://";
std::string hostname;
if (is_prefix(url.c_str(), HTTP)) {
hostname = url.substr(sizeof(HTTP) - 1);
} else if (is_prefix(url.c_str(), HTTPS)) {
hostname = url.substr(sizeof(HTTPS) - 1);
} else {
S3FS_PRN_EXIT("url does not begin with http:// or https://");
abort();
}
size_t idx;
if ((idx = hostname.find('/')) != std::string::npos) {
return hostname.substr(0, idx);
} else {
return hostname;
}
}
std::string get_bucket_host()
{
if(!pathrequeststyle){
return bucket + "." + url_to_host(s3host);
}
return url_to_host(s3host);
}
const char* getCurlDebugHead(curl_infotype type)
{
const char* unknown = "";
const char* dataIn = "BODY <";
const char* dataOut = "BODY >";
const char* headIn = "<";
const char* headOut = ">";
switch(type){
case CURLINFO_DATA_IN:
return dataIn;
case CURLINFO_DATA_OUT:
return dataOut;
case CURLINFO_HEADER_IN:
return headIn;
case CURLINFO_HEADER_OUT:
return headOut;
default:
break;
}
return unknown;
}
//
// compare ETag ignoring quotes and case
//
bool etag_equals(std::string s1, std::string s2)
{
if(s1.length() > 1 && s1[0] == '\"' && *s1.rbegin() == '\"'){
s1.erase(s1.size() - 1);
s1.erase(0, 1);
}
if(s2.length() > 1 && s2[0] == '\"' && *s2.rbegin() == '\"'){
s2.erase(s2.size() - 1);
s2.erase(0, 1);
}
return 0 == strcasecmp(s1.c_str(), s2.c_str());
}
/*
* 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
*/

58
src/curl_util.h Normal file
View File

@ -0,0 +1,58 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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.
*/
#ifndef S3FS_CURL_UTIL_H_
#define S3FS_CURL_UTIL_H_
#include <curl/curl.h>
class sse_type_t;
//----------------------------------------------
// Functions
//----------------------------------------------
std::string GetContentMD5(int fd);
struct curl_slist* curl_slist_sort_insert(struct curl_slist* list, const char* data);
struct curl_slist* curl_slist_sort_insert(struct curl_slist* list, const char* key, const char* value);
struct curl_slist* curl_slist_remove(struct curl_slist* list, const char* key);
std::string get_sorted_header_keys(const struct curl_slist* list);
std::string get_canonical_headers(const struct curl_slist* list, bool only_amz = false);
std::string get_header_value(const struct curl_slist* list, const std::string &key);
bool MakeUrlResource(const char* realpath, std::string& resourcepath, std::string& url);
std::string prepare_url(const char* url);
bool get_object_sse_type(const char* path, sse_type_t& ssetype, std::string& ssevalue); // implement in s3fs.cpp
bool make_md5_from_binary(const char* pstr, size_t length, std::string& md5);
std::string url_to_host(const std::string &url);
std::string get_bucket_host();
const char* getCurlDebugHead(curl_infotype type);
bool etag_equals(std::string s1, std::string s2);
#endif // S3FS_CURL_UTIL_H_
/*
* 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
*/

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright 2007-2008 Randy Rizun <rrizun@gmail.com>
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,124 +17,11 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef FD_CACHE_H_
#define FD_CACHE_H_
//------------------------------------------------
// CacheFileStat
//------------------------------------------------
class CacheFileStat
{
private:
std::string path;
int fd;
#ifndef S3FS_FDCACHE_H_
#define S3FS_FDCACHE_H_
private:
static bool MakeCacheFileStatPath(const char* path, std::string& sfile_path, bool is_create_dir = true);
public:
static bool DeleteCacheFileStat(const char* path);
CacheFileStat(const char* tpath = NULL);
~CacheFileStat();
bool Open(void);
bool Release(void);
bool SetPath(const char* tpath, bool is_open = true);
int GetFd(void) const { return fd; }
};
//------------------------------------------------
// fdpage & PageList
//------------------------------------------------
// page block information
struct fdpage
{
off_t offset;
size_t bytes;
bool init;
fdpage(off_t start = 0, size_t size = 0, bool is_init = false)
: offset(start), bytes(size), init(is_init) {}
off_t next(void) const { return (offset + bytes); }
off_t end(void) const { return (0 < bytes ? offset + bytes - 1 : 0); }
};
typedef std::list<struct fdpage*> fdpage_list_t;
//
// Management of loading area/modifying
//
class PageList
{
private:
fdpage_list_t pages;
private:
void Clear(void);
public:
static void FreeList(fdpage_list_t& list);
PageList(off_t size = 0, bool is_init = false);
~PageList();
off_t Size(void) const;
int Resize(off_t size, bool is_init);
int Init(off_t size, bool is_init);
bool IsInit(off_t start, off_t size);
bool SetInit(off_t start, off_t size, bool is_init = true);
bool FindUninitPage(off_t start, off_t& resstart, size_t& ressize);
int GetUninitPages(fdpage_list_t& uninit_list, off_t start = 0);
bool Serialize(CacheFileStat& file, bool is_output);
void Dump(void);
};
//------------------------------------------------
// class FdEntity
//------------------------------------------------
class FdEntity
{
private:
pthread_mutex_t fdent_lock;
bool is_lock_init;
PageList pagelist;
int refcnt; // reference count
std::string path; // object path
std::string cachepath; // local cache file path
int fd; // file discriptor(tmp file or cache file)
FILE* file; // file pointer(tmp file or cache file)
bool is_modify; // if file is changed, this flag is true
private:
void Clear(void);
int Dup(void);
bool SetAllStatus(bool is_enable);
public:
FdEntity(const char* tpath = NULL, const char* cpath = NULL);
~FdEntity();
void Close(void);
bool IsOpen(void) const { return (-1 != fd); }
int Open(off_t size = -1, time_t time = -1);
const char* GetPath(void) const { return path.c_str(); }
int GetFd(void) const { return fd; }
int SetMtime(time_t time);
bool GetSize(off_t& size);
bool GetMtime(time_t& time);
bool GetStats(struct stat& st);
bool SetAllEnable(void) { return SetAllStatus(true); }
bool SetAllDisable(void) { return SetAllStatus(false); }
bool LoadFull(off_t* size = NULL, bool force_load = false);
int Load(off_t start, off_t size);
int RowFlush(const char* tpath, headers_t& meta, bool force_sync = false);
int Flush(headers_t& meta, bool force_sync = false) { return RowFlush(NULL, meta, force_sync); }
ssize_t Read(char* bytes, off_t start, size_t size, bool force_load = false);
ssize_t Write(const char* bytes, off_t start, size_t size);
};
typedef std::map<std::string, class FdEntity*> fdent_map_t; // key=path, value=FdEntity*
#include "fdcache_entity.h"
//------------------------------------------------
// class FdManager
@ -142,43 +29,79 @@ typedef std::map<std::string, class FdEntity*> fdent_map_t; // key=path, value
class FdManager
{
private:
static FdManager singleton;
static pthread_mutex_t fd_manager_lock;
static bool is_lock_init;
static std::string cache_dir;
static size_t page_size;
static FdManager singleton;
static pthread_mutex_t fd_manager_lock;
static pthread_mutex_t cache_cleanup_lock;
static pthread_mutex_t reserved_diskspace_lock;
static bool is_lock_init;
static std::string cache_dir;
static bool check_cache_dir_exist;
static off_t free_disk_space; // limit free disk space
static off_t fake_used_disk_space; // difference between fake free disk space and actual at startup(for test/debug)
static std::string check_cache_output;
static bool checked_lseek;
static bool have_lseek_hole;
static std::string tmp_dir;
fdent_map_t fent;
fdent_map_t fent;
private:
static off_t GetFreeDiskSpace(const char* path);
void CleanupCacheDirInternal(const std::string &path = "");
bool RawCheckAllCache(FILE* fp, const char* cache_stat_top_dir, const char* sub_path, int& total_file_cnt, int& err_file_cnt, int& err_dir_cnt);
static bool IsDir(const std::string* dir);
public:
FdManager();
~FdManager();
FdManager();
~FdManager();
// Reference singleton
static FdManager* get(void) { return &singleton; }
// Reference singleton
static FdManager* get() { return &singleton; }
static bool DeleteCacheDirectory(void);
static int DeleteCacheFile(const char* path);
static bool SetCacheDir(const char* dir);
static bool IsCacheDir(void) { return (0 < FdManager::cache_dir.size()); }
static const char* GetCacheDir(void) { return FdManager::cache_dir.c_str(); }
static size_t SetPageSize(size_t size);
static size_t GetPageSize(void) { return FdManager::page_size; }
static bool MakeCachePath(const char* path, std::string& cache_path, bool is_create_dir = true);
static bool DeleteCacheDirectory();
static int DeleteCacheFile(const char* path);
static bool SetCacheDir(const char* dir);
static bool IsCacheDir() { return !FdManager::cache_dir.empty(); }
static const char* GetCacheDir() { return FdManager::cache_dir.c_str(); }
static bool SetCacheCheckOutput(const char* path);
static const char* GetCacheCheckOutput() { return FdManager::check_cache_output.c_str(); }
static bool MakeCachePath(const char* path, std::string& cache_path, bool is_create_dir = true, bool is_mirror_path = false);
static bool CheckCacheTopDir();
static bool MakeRandomTempPath(const char* path, std::string& tmppath);
static bool SetCheckCacheDirExist(bool is_check);
static bool CheckCacheDirExist();
static bool HasOpenEntityFd(const char* path);
static off_t GetEnsureFreeDiskSpace();
static off_t SetEnsureFreeDiskSpace(off_t size);
static bool InitFakeUsedDiskSize(off_t fake_freesize);
static bool IsSafeDiskSpace(const char* path, off_t size);
static void FreeReservedDiskSpace(off_t size);
static bool ReserveDiskSpace(off_t size);
static bool HaveLseekHole();
static bool SetTmpDir(const char* dir);
static bool CheckTmpDirExist();
static FILE* MakeTempFile();
FdEntity* GetFdEntity(const char* path);
FdEntity* Open(const char* path, off_t size = -1, time_t time = -1, bool force_tmpfile = false, bool is_create = true);
FdEntity* ExistOpen(const char* path) { return Open(path, -1, -1, false, false); }
bool Close(FdEntity* ent);
// Return FdEntity associated with path, returning NULL on error. This operation increments the reference count; callers must decrement via Close after use.
FdEntity* GetFdEntity(const char* path, int& existfd, bool newfd = true, bool lock_already_held = false);
FdEntity* Open(int& fd, const char* path, headers_t* pmeta, off_t size, time_t time, int flags, bool force_tmpfile, bool is_create, AutoLock::Type type);
FdEntity* GetExistFdEntity(const char* path, int existfd = -1);
FdEntity* OpenExistFdEntity(const char* path, int& fd, int flags = O_RDONLY);
void Rename(const std::string &from, const std::string &to);
bool Close(FdEntity* ent, int fd);
bool ChangeEntityToTempPath(FdEntity* ent, const char* path);
void CleanupCacheDir();
bool CheckAllCache();
};
#endif // FD_CACHE_H_
#endif // S3FS_FDCACHE_H_
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
* vim600: expandtab sw=4 ts=4 fdm=marker
* vim<600: expandtab sw=4 ts=4
*/

165
src/fdcache_auto.cpp Normal file
View File

@ -0,0 +1,165 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Takeshi Nakatani <ggtakec.com>
*
* 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 <cstdio>
#include <cstdlib>
#include "common.h"
#include "s3fs.h"
#include "fdcache_auto.h"
#include "fdcache.h"
//------------------------------------------------
// AutoFdEntity methods
//------------------------------------------------
AutoFdEntity::AutoFdEntity() : pFdEntity(NULL), pseudo_fd(-1)
{
}
// [NOTE]
// The copy constructor should not be called, then this is private method.
// Even if it is called, the consistency of the number of
// references can be maintained, but this case is not assumed.
//
AutoFdEntity::AutoFdEntity(AutoFdEntity& other) : pFdEntity(NULL), pseudo_fd(-1)
{
S3FS_PRN_WARN("This method should not be called. Please check the caller.");
if(other.pFdEntity){
if(-1 != (pseudo_fd = other.pFdEntity->Dup(other.pseudo_fd))){
pFdEntity = other.pFdEntity;
}else{
S3FS_PRN_ERR("Failed duplicating fd in AutoFdEntity.");
}
}
}
AutoFdEntity::~AutoFdEntity()
{
Close();
}
bool AutoFdEntity::Close()
{
if(pFdEntity){
if(!FdManager::get()->Close(pFdEntity, pseudo_fd)){
S3FS_PRN_ERR("Failed to close fdentity.");
return false;
}
pFdEntity = NULL;
pseudo_fd = -1;
}
return true;
}
// [NOTE]
// This method touches the internal fdentity with.
// This is used to keep the file open.
//
int AutoFdEntity::Detach()
{
if(!pFdEntity){
S3FS_PRN_ERR("Does not have a associated FdEntity.");
return -1;
}
int fd = pseudo_fd;
pseudo_fd = -1;
pFdEntity = NULL;
return fd;
}
bool AutoFdEntity::Attach(const char* path, int existfd)
{
Close();
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);
return false;
}
pseudo_fd = existfd;
return true;
}
FdEntity* AutoFdEntity::Open(const char* path, headers_t* pmeta, off_t size, time_t time, int flags, bool force_tmpfile, bool is_create, AutoLock::Type type)
{
Close();
if(NULL == (pFdEntity = FdManager::get()->Open(pseudo_fd, path, pmeta, size, time, flags, force_tmpfile, is_create, type))){
pseudo_fd = -1;
return NULL;
}
return pFdEntity;
}
// [NOTE]
// the fd obtained by this method is not a newly created pseudo fd.
//
FdEntity* AutoFdEntity::GetExistFdEntity(const char* path, int existfd)
{
Close();
FdEntity* ent;
if(NULL == (ent = FdManager::get()->GetExistFdEntity(path, existfd))){
return NULL;
}
return ent;
}
FdEntity* AutoFdEntity::OpenExistFdEntity(const char* path, int flags)
{
Close();
if(NULL == (pFdEntity = FdManager::get()->OpenExistFdEntity(path, pseudo_fd, flags))){
return NULL;
}
return pFdEntity;
}
// [NOTE]
// This operator should not be called, then this is private method.
// Even if it is called, the consistency of the number of
// references can be maintained, but this case is not assumed.
//
bool AutoFdEntity::operator=(AutoFdEntity& other)
{
S3FS_PRN_WARN("This method should not be called. Please check the caller.");
Close();
if(other.pFdEntity){
if(-1 != (pseudo_fd = other.pFdEntity->Dup(other.pseudo_fd))){
pFdEntity = other.pFdEntity;
}else{
S3FS_PRN_ERR("Failed duplicating fd in AutoFdEntity.");
return false;
}
}
return true;
}
/*
* 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
*/

68
src/fdcache_auto.h Normal file
View File

@ -0,0 +1,68 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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.
*/
#ifndef S3FS_FDCACHE_AUTO_H_
#define S3FS_FDCACHE_AUTO_H_
#include "autolock.h"
#include "fdcache_entity.h"
//------------------------------------------------
// class AutoFdEntity
//------------------------------------------------
// A class that opens fdentry and closes it automatically.
// This class object is used to prevent inconsistencies in
// the number of references in fdentry.
// The methods are wrappers to the method of the FdManager class.
//
class AutoFdEntity
{
private:
FdEntity* pFdEntity;
int pseudo_fd;
private:
AutoFdEntity(AutoFdEntity& other);
bool operator=(AutoFdEntity& other);
public:
AutoFdEntity();
~AutoFdEntity();
bool Close();
int Detach();
bool Attach(const char* path, int existfd);
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, AutoLock::Type type);
FdEntity* GetExistFdEntity(const char* path, int existfd = -1);
FdEntity* OpenExistFdEntity(const char* path, int flags = O_RDONLY);
};
#endif // S3FS_FDCACHE_AUTO_H_
/*
* 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
*/

2180
src/fdcache_entity.cpp Normal file

File diff suppressed because it is too large Load Diff

147
src/fdcache_entity.h Normal file
View File

@ -0,0 +1,147 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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.
*/
#ifndef S3FS_FDCACHE_ENTITY_H_
#define S3FS_FDCACHE_ENTITY_H_
#include "autolock.h"
#include "fdcache_page.h"
#include "fdcache_fdinfo.h"
#include "metaheader.h"
//------------------------------------------------
// class FdEntity
//------------------------------------------------
class FdEntity
{
private:
static bool mixmultipart; // whether multipart uploading can use copy api.
pthread_mutex_t fdent_lock;
bool is_lock_init;
std::string path; // object path
int physical_fd; // physical file(cache or temporary file) descriptor
fdinfo_map_t pseudo_fd_map; // pseudo file descriptor information map
FILE* pfile; // file pointer(tmp file or cache file)
ino_t inode; // inode number for cache file
headers_t orgmeta; // original headers at opening
off_t size_orgmeta; // original file size in original headers
pthread_mutex_t fdent_data_lock;// protects the following members
PageList pagelist;
std::string cachepath; // local cache file path
// (if this is empty, does not load/save pagelist.)
std::string mirrorpath; // mirror file path to local cache file path
bool is_meta_pending;
struct timespec holding_mtime; // if mtime is updated while the file is open, it is set time_t value
private:
static int FillFile(int fd, unsigned char byte, off_t size, off_t start);
static ino_t GetInode(int fd);
void Clear();
ino_t GetInode();
int OpenMirrorFile();
int NoCacheLoadAndPost(PseudoFdInfo* pseudo_obj, off_t start = 0, off_t size = 0); // size=0 means loading to end
PseudoFdInfo* CheckPseudoFdFlags(int fd, bool writable, bool lock_already_held = false);
bool IsUploading(bool lock_already_held = false);
bool SetAllStatus(bool is_loaded); // [NOTE] not locking
bool SetAllStatusUnloaded() { return SetAllStatus(false); }
int NoCachePreMultipartPost(PseudoFdInfo* pseudo_obj);
int NoCacheMultipartPost(PseudoFdInfo* pseudo_obj, int tgfd, off_t start, off_t size);
int NoCacheCompleteMultipartPost(PseudoFdInfo* pseudo_obj);
int RowFlushNoMultipart(PseudoFdInfo* pseudo_obj, const char* tpath);
int RowFlushMultipart(PseudoFdInfo* pseudo_obj, const char* tpath);
int RowFlushMixMultipart(PseudoFdInfo* pseudo_obj, const char* tpath);
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 WriteMixMultipart(PseudoFdInfo* pseudo_obj, const char* bytes, off_t start, size_t size);
int UploadPendingMeta();
public:
static bool GetNoMixMultipart() { return mixmultipart; }
static bool SetNoMixMultipart();
explicit FdEntity(const char* tpath = NULL, const char* cpath = NULL);
~FdEntity();
void Close(int fd);
bool IsOpen() const { return (-1 != physical_fd); }
bool FindPseudoFd(int fd, bool lock_already_held = false);
int Open(headers_t* pmeta, off_t size, time_t time, int flags, AutoLock::Type type);
bool LoadAll(int fd, headers_t* pmeta = NULL, off_t* size = NULL, bool force_load = false);
int Dup(int fd, bool lock_already_held = false);
int OpenPseudoFd(int flags = O_RDONLY, bool lock_already_held = false);
int GetOpenCount(bool lock_already_held = false);
const char* GetPath() const { return path.c_str(); }
bool RenamePath(const std::string& newpath, std::string& fentmapkey);
int GetPhysicalFd() const { return physical_fd; }
bool IsModified() const;
bool MergeOrgMeta(headers_t& updatemeta);
bool GetStats(struct stat& st, bool lock_already_held = false);
int SetCtime(struct timespec time, bool lock_already_held = false);
int SetAtime(struct timespec time, bool lock_already_held = false);
int SetMCtime(struct timespec mtime, struct timespec ctime, bool lock_already_held = false);
bool UpdateCtime();
bool UpdateAtime();
bool UpdateMtime(bool clear_holding_mtime = false);
bool UpdateMCtime();
bool SetHoldingMtime(struct timespec mtime, bool lock_already_held = false);
bool ClearHoldingMtime(bool lock_already_held = false);
bool GetSize(off_t& size);
bool GetXattr(std::string& xattr);
bool SetXattr(const std::string& xattr);
bool SetMode(mode_t mode);
bool SetUId(uid_t uid);
bool SetGId(gid_t gid);
bool SetContentType(const char* path);
int Load(off_t start, off_t size, AutoLock::Type type, bool is_modified_flag = false); // size=0 means loading to end
off_t BytesModified();
int RowFlush(int fd, const char* tpath, bool force_sync = false);
int Flush(int fd, bool force_sync = false) { return RowFlush(fd, NULL, force_sync); }
ssize_t Read(int fd, char* bytes, off_t start, size_t size, bool force_load = false);
ssize_t Write(int fd, const char* bytes, off_t start, size_t size);
bool ReserveDiskSpace(off_t size);
bool PunchHole(off_t start = 0, size_t size = 0);
// Indicate that a new file's is dirty. This ensures that both metadata and data are synced during flush.
void MarkDirtyNewFile() {
pagelist.SetPageLoadedStatus(0, 1, PageList::PAGE_LOAD_MODIFIED);
is_meta_pending = true;
}
};
typedef std::map<std::string, class FdEntity*> fdent_map_t; // key=path, value=FdEntity*
#endif // S3FS_FDCACHE_ENTITY_H_
/*
* 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
*/

257
src/fdcache_fdinfo.cpp Normal file
View File

@ -0,0 +1,257 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Takeshi Nakatani <ggtakec.com>
*
* 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 <cstdio>
#include <cstdlib>
#include <algorithm>
#include "common.h"
#include "s3fs.h"
#include "fdcache_fdinfo.h"
#include "fdcache_pseudofd.h"
#include "autolock.h"
//------------------------------------------------
// PseudoFdInfo methods
//------------------------------------------------
PseudoFdInfo::PseudoFdInfo(int fd, int open_flags) : pseudo_fd(-1), physical_fd(fd), flags(0) //, is_lock_init(false)
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
#if S3FS_PTHREAD_ERRORCHECK
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
#endif
int result;
if(0 != (result = pthread_mutex_init(&upload_list_lock, &attr))){
S3FS_PRN_CRIT("failed to init upload_list_lock: %d", result);
abort();
}
is_lock_init = true;
if(-1 != physical_fd){
pseudo_fd = PseudoFdManager::Get();
flags = open_flags;
}
}
PseudoFdInfo::~PseudoFdInfo()
{
if(is_lock_init){
int result;
if(0 != (result = pthread_mutex_destroy(&upload_list_lock))){
S3FS_PRN_CRIT("failed to destroy upload_list_lock: %d", result);
abort();
}
is_lock_init = false;
}
Clear();
}
bool PseudoFdInfo::Clear()
{
if(-1 != pseudo_fd){
PseudoFdManager::Release(pseudo_fd);
}
pseudo_fd = -1;
physical_fd = -1;
return true;
}
bool PseudoFdInfo::Set(int fd, int open_flags)
{
if(-1 == fd){
return false;
}
Clear();
physical_fd = fd;
pseudo_fd = PseudoFdManager::Get();
flags = open_flags;
return true;
}
bool PseudoFdInfo::Writable() const
{
if(-1 == pseudo_fd){
return false;
}
if(0 == (flags & (O_WRONLY | O_RDWR))){
return false;
}
return true;
}
bool PseudoFdInfo::Readable() const
{
if(-1 == pseudo_fd){
return false;
}
// O_RDONLY is 0x00, it means any pattern is readable.
return true;
}
bool PseudoFdInfo::ClearUploadInfo(bool is_cancel_mp, bool lock_already_held)
{
AutoLock auto_lock(&upload_list_lock, lock_already_held ? AutoLock::ALREADY_LOCKED : AutoLock::NONE);
if(is_cancel_mp){
// [TODO]
// If we have any uploaded parts, we should delete them here.
// We haven't implemented it yet, but it will be implemented in the future.
// (User can delete them in the utility mode of s3fs.)
//
S3FS_PRN_INFO("Implementation of cancellation process for multipart upload is awaited.");
}
upload_id.erase();
upload_list.clear();
ClearUntreated(true);
return true;
}
bool PseudoFdInfo::InitialUploadInfo(const std::string& id)
{
AutoLock auto_lock(&upload_list_lock);
if(!ClearUploadInfo(true, true)){
return false;
}
upload_id = id;
return true;
}
bool PseudoFdInfo::GetUploadId(std::string& id) const
{
if(IsUploading()){
S3FS_PRN_ERR("Multipart Upload has not started yet.");
return false;
}
id = upload_id;
return true;
}
bool PseudoFdInfo::GetEtaglist(etaglist_t& list)
{
if(IsUploading()){
S3FS_PRN_ERR("Multipart Upload has not started yet.");
return false;
}
AutoLock auto_lock(&upload_list_lock);
list.clear();
for(filepart_list_t::const_iterator iter = upload_list.begin(); iter != upload_list.end(); ++iter){
if(iter->petag){
list.push_back(*(iter->petag));
}else{
S3FS_PRN_ERR("The pointer to the etag string is null(internal error).");
return false;
}
}
return !list.empty();
}
// [NOTE]
// This method adds a part for a multipart upload.
// The added new part must be an area that is exactly continuous with the
// immediately preceding part.
// An error will occur if it is discontinuous or if it overlaps with an
// existing area.
//
bool PseudoFdInfo::AppendUploadPart(off_t start, off_t size, bool is_copy, int* ppartnum, std::string** ppetag)
{
if(IsUploading()){
S3FS_PRN_ERR("Multipart Upload has not started yet.");
return false;
}
AutoLock auto_lock(&upload_list_lock);
off_t next_start_pos = 0;
if(!upload_list.empty()){
next_start_pos = upload_list.back().startpos + upload_list.back().size;
}
if(start != next_start_pos){
S3FS_PRN_ERR("The expected starting position for the next part is %lld, but %lld was specified.", static_cast<long long int>(next_start_pos), static_cast<long long int>(start));
return false;
}
// add new part
etag_entities.push_back(std::string("")); // [NOTE] Create the etag entity and register it in the list.
std::string& etag_entity = etag_entities.back();
filepart newpart(false, physical_fd, start, size, is_copy, &etag_entity);
upload_list.push_back(newpart);
// set part number
if(ppartnum){
*ppartnum = static_cast<int>(upload_list.size());
}
// set etag pointer
if(ppetag){
*ppetag = &etag_entity;
}
return true;
}
void PseudoFdInfo::ClearUntreated(bool lock_already_held)
{
AutoLock auto_lock(&upload_list_lock, lock_already_held ? AutoLock::ALREADY_LOCKED : AutoLock::NONE);
untreated_list.ClearAll();
}
bool PseudoFdInfo::ClearUntreated(off_t start, off_t size)
{
AutoLock auto_lock(&upload_list_lock);
return untreated_list.ClearParts(start, size);
}
bool PseudoFdInfo::GetUntreated(off_t& start, off_t& size, off_t max_size, off_t min_size)
{
AutoLock auto_lock(&upload_list_lock);
return untreated_list.GetPart(start, size, max_size, min_size);
}
bool PseudoFdInfo::GetLastUntreated(off_t& start, off_t& size, off_t max_size, off_t min_size)
{
AutoLock auto_lock(&upload_list_lock);
return untreated_list.GetLastUpdatedPart(start, size, max_size, min_size);
}
bool PseudoFdInfo::AddUntreated(off_t start, off_t size)
{
AutoLock auto_lock(&upload_list_lock);
return untreated_list.AddPart(start, size);
}
/*
* 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
*/

84
src/fdcache_fdinfo.h Normal file
View File

@ -0,0 +1,84 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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.
*/
#ifndef S3FS_FDCACHE_FDINFO_H_
#define S3FS_FDCACHE_FDINFO_H_
#include "fdcache_untreated.h"
//------------------------------------------------
// Class PseudoFdInfo
//------------------------------------------------
class PseudoFdInfo
{
private:
int pseudo_fd;
int physical_fd;
int flags; // flags at open
std::string upload_id;
filepart_list_t upload_list;
UntreatedParts untreated_list; // list of untreated parts that have been written and not yet uploaded(for streamupload)
etaglist_t etag_entities; // list of etag string entities(to maintain the etag entity even if MPPART_INFO is destroyed)
bool is_lock_init;
pthread_mutex_t upload_list_lock; // protects upload_id and upload_list
private:
bool Clear();
public:
PseudoFdInfo(int fd = -1, int open_flags = 0);
~PseudoFdInfo();
int GetPhysicalFd() const { return physical_fd; }
int GetPseudoFd() const { return pseudo_fd; }
int GetFlags() const { return flags; }
bool Writable() const;
bool Readable() const;
bool Set(int fd, int open_flags);
bool ClearUploadInfo(bool is_clear_part = false, bool lock_already_held = false);
bool InitialUploadInfo(const std::string& id);
bool IsUploading() const { return !upload_id.empty(); }
bool GetUploadId(std::string& id) const;
bool GetEtaglist(etaglist_t& list);
bool AppendUploadPart(off_t start, off_t size, bool is_copy = false, int* ppartnum = NULL, std::string** ppetag = NULL);
void ClearUntreated(bool lock_already_held = false);
bool ClearUntreated(off_t start, off_t size);
bool GetUntreated(off_t& start, off_t& size, off_t max_size, off_t min_size = MIN_MULTIPART_SIZE);
bool GetLastUntreated(off_t& start, off_t& size, off_t max_size, off_t min_size = MIN_MULTIPART_SIZE);
bool AddUntreated(off_t start, off_t size);
};
typedef std::map<int, class PseudoFdInfo*> fdinfo_map_t;
#endif // S3FS_FDCACHE_FDINFO_H_
/*
* 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
*/

986
src/fdcache_page.cpp Normal file
View File

@ -0,0 +1,986 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Takeshi Nakatani <ggtakec.com>
*
* 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 <cstdio>
#include <cstdlib>
#include <cerrno>
#include <unistd.h>
#include <sstream>
#include "common.h"
#include "s3fs.h"
#include "fdcache_page.h"
#include "string_util.h"
//------------------------------------------------
// Symbols
//------------------------------------------------
static const int CHECK_CACHEFILE_PART_SIZE = 1024 * 16; // Buffer size in PageList::CheckZeroAreaInFile()
//------------------------------------------------
// fdpage_list_t utility
//------------------------------------------------
// Inline function for repeated processing
inline void raw_add_compress_fdpage_list(fdpage_list_t& pagelist, fdpage& page, bool ignore_load, bool ignore_modify, bool default_load, bool default_modify)
{
if(0 < page.bytes){
// [NOTE]
// The page variable is subject to change here.
//
if(ignore_load){
page.loaded = default_load;
}
if(ignore_modify){
page.modified = default_modify;
}
pagelist.push_back(page);
}
}
// Compress the page list
//
// ignore_load: Ignore the flag of loaded member and compress
// ignore_modify: Ignore the flag of modified member and compress
// default_load: loaded flag value in the list after compression when ignore_load=true
// default_modify: modified flag value in the list after compression when default_modify=true
//
// NOTE: ignore_modify and ignore_load cannot both be true.
//
static fdpage_list_t raw_compress_fdpage_list(const fdpage_list_t& pages, bool ignore_load, bool ignore_modify, bool default_load, bool default_modify)
{
fdpage_list_t compressed_pages;
fdpage tmppage;
bool is_first = true;
for(fdpage_list_t::const_iterator iter = pages.begin(); iter != pages.end(); ++iter){
if(!is_first){
if( (!ignore_load && (tmppage.loaded != iter->loaded )) ||
(!ignore_modify && (tmppage.modified != iter->modified)) )
{
// Different from the previous area, add it to list
raw_add_compress_fdpage_list(compressed_pages, tmppage, ignore_load, ignore_modify, default_load, default_modify);
// keep current area
tmppage = fdpage(iter->offset, iter->bytes, (ignore_load ? default_load : iter->loaded), (ignore_modify ? default_modify : iter->modified));
}else{
// Same as the previous area
if(tmppage.next() != iter->offset){
// These are not contiguous areas, add it to list
raw_add_compress_fdpage_list(compressed_pages, tmppage, ignore_load, ignore_modify, default_load, default_modify);
// keep current area
tmppage = fdpage(iter->offset, iter->bytes, (ignore_load ? default_load : iter->loaded), (ignore_modify ? default_modify : iter->modified));
}else{
// These are contiguous areas
// add current area
tmppage.bytes += iter->bytes;
}
}
}else{
// first erea
is_first = false;
// keep current area
tmppage = fdpage(iter->offset, iter->bytes, (ignore_load ? default_load : iter->loaded), (ignore_modify ? default_modify : iter->modified));
}
}
// add last area
if(!is_first){
raw_add_compress_fdpage_list(compressed_pages, tmppage, ignore_load, ignore_modify, default_load, default_modify);
}
return compressed_pages;
}
static fdpage_list_t compress_fdpage_list_ignore_modify(const fdpage_list_t& pages, bool default_modify)
{
return raw_compress_fdpage_list(pages, /* ignore_load= */ false, /* ignore_modify= */ true, /* default_load= */false, /* default_modify= */default_modify);
}
static fdpage_list_t compress_fdpage_list_ignore_load(const fdpage_list_t& pages, bool default_load)
{
return raw_compress_fdpage_list(pages, /* ignore_load= */ true, /* ignore_modify= */ false, /* default_load= */default_load, /* default_modify= */false);
}
static fdpage_list_t compress_fdpage_list(const fdpage_list_t& pages)
{
return raw_compress_fdpage_list(pages, /* ignore_load= */ false, /* ignore_modify= */ false, /* default_load= */false, /* default_modify= */false);
}
static fdpage_list_t parse_partsize_fdpage_list(const fdpage_list_t& pages, off_t max_partsize)
{
fdpage_list_t parsed_pages;
for(fdpage_list_t::const_iterator iter = pages.begin(); iter != pages.end(); ++iter){
if(iter->modified){
// modified page
fdpage tmppage = *iter;
for(off_t start = iter->offset, rest_bytes = iter->bytes; 0 < rest_bytes; ){
if((max_partsize * 2) < rest_bytes){
// do parse
tmppage.offset = start;
tmppage.bytes = max_partsize;
parsed_pages.push_back(tmppage);
start += max_partsize;
rest_bytes -= max_partsize;
}else{
// Since the number of remaining bytes is less than twice max_partsize,
// one of the divided areas will be smaller than max_partsize.
// Therefore, this area at the end should not be divided.
tmppage.offset = start;
tmppage.bytes = rest_bytes;
parsed_pages.push_back(tmppage);
start += rest_bytes;
rest_bytes = 0;
}
}
}else{
// not modified page is not parsed
parsed_pages.push_back(*iter);
}
}
return parsed_pages;
}
//------------------------------------------------
// PageList class methods
//------------------------------------------------
//
// Examine and return the status of each block in the file.
//
// Assuming the file is a sparse file, check the HOLE and DATA areas
// and return it in fdpage_list_t. The loaded flag of each fdpage is
// set to false for HOLE blocks and true for DATA blocks.
//
bool PageList::GetSparseFilePages(int fd, size_t file_size, fdpage_list_t& sparse_list)
{
// [NOTE]
// Express the status of the cache file using fdpage_list_t.
// There is a hole in the cache file(sparse file), and the
// state of this hole is expressed by the "loaded" member of
// struct fdpage. (the "modified" member is not used)
//
if(0 == file_size){
// file is empty
return true;
}
bool is_hole = false;
off_t hole_pos = lseek(fd, 0, SEEK_HOLE);
off_t data_pos = lseek(fd, 0, SEEK_DATA);
if(-1 == hole_pos && -1 == data_pos){
S3FS_PRN_ERR("Could not find the first position both HOLE and DATA in the file(physical_fd=%d).", fd);
return false;
}else if(-1 == hole_pos){
is_hole = false;
}else if(-1 == data_pos){
is_hole = true;
}else if(hole_pos < data_pos){
is_hole = true;
}else{
is_hole = false;
}
for(off_t cur_pos = 0, next_pos = 0; 0 <= cur_pos; cur_pos = next_pos, is_hole = !is_hole){
fdpage page;
page.offset = cur_pos;
page.loaded = !is_hole;
page.modified = false;
next_pos = lseek(fd, cur_pos, (is_hole ? SEEK_DATA : SEEK_HOLE));
if(-1 == next_pos){
page.bytes = static_cast<off_t>(file_size - cur_pos);
}else{
page.bytes = next_pos - cur_pos;
}
sparse_list.push_back(page);
}
return true;
}
//
// Confirm that the specified area is ZERO
//
bool PageList::CheckZeroAreaInFile(int fd, off_t start, size_t bytes)
{
char* readbuff = new char[CHECK_CACHEFILE_PART_SIZE];
for(size_t comp_bytes = 0, check_bytes = 0; comp_bytes < bytes; comp_bytes += check_bytes){
if(CHECK_CACHEFILE_PART_SIZE < (bytes - comp_bytes)){
check_bytes = CHECK_CACHEFILE_PART_SIZE;
}else{
check_bytes = bytes - comp_bytes;
}
bool found_bad_data = false;
ssize_t read_bytes;
if(-1 == (read_bytes = pread(fd, readbuff, check_bytes, (start + comp_bytes)))){
S3FS_PRN_ERR("Something error is occurred in reading %zu bytes at %lld from file(physical_fd=%d).", check_bytes, static_cast<long long int>(start + comp_bytes), fd);
found_bad_data = true;
}else{
check_bytes = static_cast<size_t>(read_bytes);
for(size_t tmppos = 0; tmppos < check_bytes; ++tmppos){
if('\0' != readbuff[tmppos]){
// found not ZERO data.
found_bad_data = true;
break;
}
}
}
if(found_bad_data){
delete[] readbuff;
return false;
}
}
delete[] readbuff;
return true;
}
//
// Checks that the specified area matches the state of the sparse file.
//
// [Parameters]
// checkpage: This is one state of the cache file, it is loaded from the stats file.
// sparse_list: This is a list of the results of directly checking the cache file status(HOLE/DATA).
// In the HOLE area, the "loaded" flag of fdpage is false. The DATA area has it set to true.
// fd: opened file discriptor to target cache file.
//
bool PageList::CheckAreaInSparseFile(const struct fdpage& checkpage, const fdpage_list_t& sparse_list, int fd, fdpage_list_t& err_area_list, fdpage_list_t& warn_area_list)
{
// Check the block status of a part(Check Area: checkpage) of the target file.
// The elements of sparse_list have 5 patterns that overlap this block area.
//
// File |<---...--------------------------------------...--->|
// Check Area (offset)<-------------------->(offset + bytes - 1)
// Area case(0) <------->
// Area case(1) <------->
// Area case(2) <-------->
// Area case(3) <---------->
// Area case(4) <----------->
// Area case(5) <----------------------------->
//
bool result = true;
for(fdpage_list_t::const_iterator iter = sparse_list.begin(); iter != sparse_list.end(); ++iter){
off_t check_start = 0;
off_t check_bytes = 0;
if((iter->offset + iter->bytes) <= checkpage.offset){
// case 0
continue; // next
}else if((checkpage.offset + checkpage.bytes) <= iter->offset){
// case 1
break; // finish
}else if(iter->offset < checkpage.offset && (iter->offset + iter->bytes) < (checkpage.offset + checkpage.bytes)){
// case 2
check_start = checkpage.offset;
check_bytes = iter->bytes - (checkpage.offset - iter->offset);
}else if(iter->offset < (checkpage.offset + checkpage.bytes) && (checkpage.offset + checkpage.bytes) < (iter->offset + iter->bytes)){
// case 3
check_start = iter->offset;
check_bytes = checkpage.bytes - (iter->offset - checkpage.offset);
}else if(checkpage.offset < iter->offset && (iter->offset + iter->bytes) < (checkpage.offset + checkpage.bytes)){
// case 4
check_start = iter->offset;
check_bytes = iter->bytes;
}else{ // (iter->offset <= checkpage.offset && (checkpage.offset + checkpage.bytes) <= (iter->offset + iter->bytes))
// case 5
check_start = checkpage.offset;
check_bytes = checkpage.bytes;
}
// check target area type
if(checkpage.loaded || checkpage.modified){
// target area must be not HOLE(DATA) area.
if(!iter->loaded){
// Found bad area, it is HOLE area.
fdpage page(check_start, check_bytes, false, false);
err_area_list.push_back(page);
result = false;
}
}else{
// target area should be HOLE area.(If it is not a block boundary, it may be a DATA area.)
if(iter->loaded){
// need to check this area's each data, it should be ZERO.
if(!PageList::CheckZeroAreaInFile(fd, check_start, static_cast<size_t>(check_bytes))){
// Discovered an area that has un-initial status data but it probably does not effect bad.
fdpage page(check_start, check_bytes, true, false);
warn_area_list.push_back(page);
result = false;
}
}
}
}
return result;
}
//------------------------------------------------
// PageList methods
//------------------------------------------------
void PageList::FreeList(fdpage_list_t& list)
{
list.clear();
}
PageList::PageList(off_t size, bool is_loaded, bool is_modified)
{
Init(size, is_loaded, is_modified);
}
PageList::PageList(const PageList& other)
{
for(fdpage_list_t::const_iterator iter = other.pages.begin(); iter != other.pages.end(); ++iter){
pages.push_back(*iter);
}
}
PageList::~PageList()
{
Clear();
}
void PageList::Clear()
{
PageList::FreeList(pages);
}
bool PageList::Init(off_t size, bool is_loaded, bool is_modified)
{
Clear();
if(0 < size){
fdpage page(0, size, is_loaded, is_modified);
pages.push_back(page);
}
return true;
}
off_t PageList::Size() const
{
if(pages.empty()){
return 0;
}
fdpage_list_t::const_reverse_iterator riter = pages.rbegin();
return riter->next();
}
bool PageList::Compress()
{
pages = compress_fdpage_list(pages);
return true;
}
bool PageList::Parse(off_t new_pos)
{
for(fdpage_list_t::iterator iter = pages.begin(); iter != pages.end(); ++iter){
if(new_pos == iter->offset){
// nothing to do
return true;
}else if(iter->offset < new_pos && new_pos < iter->next()){
fdpage page(iter->offset, new_pos - iter->offset, iter->loaded, iter->modified);
iter->bytes -= (new_pos - iter->offset);
iter->offset = new_pos;
pages.insert(iter, page);
return true;
}
}
return false;
}
bool PageList::Resize(off_t size, bool is_loaded, bool is_modified)
{
off_t total = Size();
if(0 == total){
Init(size, is_loaded, is_modified);
}else if(total < size){
// add new area
fdpage page(total, (size - total), is_loaded, is_modified);
pages.push_back(page);
}else if(size < total){
// cut area
for(fdpage_list_t::iterator iter = pages.begin(); iter != pages.end(); ){
if(iter->next() <= size){
++iter;
}else{
if(size <= iter->offset){
iter = pages.erase(iter);
}else{
iter->bytes = size - iter->offset;
}
}
}
}else{ // total == size
// nothing to do
}
// compress area
return Compress();
}
bool PageList::IsPageLoaded(off_t start, off_t size) const
{
for(fdpage_list_t::const_iterator iter = pages.begin(); iter != pages.end(); ++iter){
if(iter->end() < start){
continue;
}
if(!iter->loaded){
return false;
}
if(0 != size && start + size <= iter->next()){
break;
}
}
return true;
}
bool PageList::SetPageLoadedStatus(off_t start, off_t size, PageList::page_status pstatus, bool is_compress)
{
off_t now_size = Size();
bool is_loaded = (PAGE_LOAD_MODIFIED == pstatus || PAGE_LOADED == pstatus);
bool is_modified = (PAGE_LOAD_MODIFIED == pstatus || PAGE_MODIFIED == pstatus);
if(now_size <= start){
if(now_size < start){
// add
Resize(start, false, is_modified); // set modified flag from now end pos to specified start pos.
}
Resize(start + size, is_loaded, is_modified);
}else if(now_size <= start + size){
// cut
Resize(start, false, false); // not changed loaded/modified flags in existing area.
// add
Resize(start + size, is_loaded, is_modified);
}else{
// start-size are inner pages area
// parse "start", and "start + size" position
Parse(start);
Parse(start + size);
// set loaded flag
for(fdpage_list_t::iterator iter = pages.begin(); iter != pages.end(); ++iter){
if(iter->end() < start){
continue;
}else if(start + size <= iter->offset){
break;
}else{
iter->loaded = is_loaded;
iter->modified = is_modified;
}
}
}
// compress area
return (is_compress ? Compress() : true);
}
bool PageList::FindUnloadedPage(off_t start, off_t& resstart, off_t& ressize) const
{
for(fdpage_list_t::const_iterator iter = pages.begin(); iter != pages.end(); ++iter){
if(start <= iter->end()){
if(!iter->loaded && !iter->modified){ // Do not load unloaded and modified areas
resstart = iter->offset;
ressize = iter->bytes;
return true;
}
}
}
return false;
}
// [NOTE]
// Accumulates the range of unload that is smaller than the Limit size.
// If you want to integrate all unload ranges, set the limit size to 0.
//
off_t PageList::GetTotalUnloadedPageSize(off_t start, off_t size, off_t limit_size) const
{
// If size is 0, it means loading to end.
if(0 == size){
if(start < Size()){
size = Size() - start;
}
}
off_t next = start + size;
off_t restsize = 0;
for(fdpage_list_t::const_iterator iter = pages.begin(); iter != pages.end(); ++iter){
if(iter->next() <= start){
continue;
}
if(next <= iter->offset){
break;
}
if(iter->loaded || iter->modified){
continue;
}
off_t tmpsize;
if(iter->offset <= start){
if(iter->next() <= next){
tmpsize = (iter->next() - start);
}else{
tmpsize = next - start; // = size
}
}else{
if(iter->next() <= next){
tmpsize = iter->next() - iter->offset; // = iter->bytes
}else{
tmpsize = next - iter->offset;
}
}
if(0 == limit_size || tmpsize < limit_size){
restsize += tmpsize;
}
}
return restsize;
}
size_t PageList::GetUnloadedPages(fdpage_list_t& unloaded_list, off_t start, off_t size) const
{
// If size is 0, it means loading to end.
if(0 == size){
if(start < Size()){
size = Size() - start;
}
}
off_t next = start + size;
for(fdpage_list_t::const_iterator iter = pages.begin(); iter != pages.end(); ++iter){
if(iter->next() <= start){
continue;
}
if(next <= iter->offset){
break;
}
if(iter->loaded || iter->modified){
continue; // already loaded or modified
}
// page area
off_t page_start = std::max(iter->offset, start);
off_t page_next = std::min(iter->next(), next);
off_t page_size = page_next - page_start;
// add list
fdpage_list_t::reverse_iterator riter = unloaded_list.rbegin();
if(riter != unloaded_list.rend() && riter->next() == page_start){
// merge to before page
riter->bytes += page_size;
}else{
fdpage page(page_start, page_size, false, false);
unloaded_list.push_back(page);
}
}
return unloaded_list.size();
}
// [NOTE]
// This method is called in advance when mixing POST and COPY in multi-part upload.
// The minimum size of each part must be 5 MB, and the data area below this must be
// downloaded from S3.
// This method checks the current PageList status and returns the area that needs
// to be downloaded so that each part is at least 5 MB.
//
bool PageList::GetPageListsForMultipartUpload(fdpage_list_t& dlpages, fdpage_list_t& mixuppages, off_t max_partsize)
{
// compress before this processing
if(!Compress()){
return false;
}
// make a list by modified flag
fdpage_list_t modified_pages = compress_fdpage_list_ignore_load(pages, false);
fdpage_list_t download_pages; // A non-contiguous page list showing the areas that need to be downloaded
fdpage_list_t mixupload_pages; // A continuous page list showing only modified flags for mixupload
fdpage prev_page;
for(fdpage_list_t::const_iterator iter = modified_pages.begin(); iter != modified_pages.end(); ++iter){
if(iter->modified){
// current is modified area
if(!prev_page.modified){
// previous is not modified area
if(prev_page.bytes < MIN_MULTIPART_SIZE){
// previous(not modified) area is too small for one multipart size,
// then all of previous area is needed to download.
download_pages.push_back(prev_page);
// previous(not modified) area is set upload area.
prev_page.modified = true;
mixupload_pages.push_back(prev_page);
}else{
// previous(not modified) area is set copy area.
prev_page.modified = false;
mixupload_pages.push_back(prev_page);
}
// set current to previous
prev_page = *iter;
}else{
// previous is modified area, too
prev_page.bytes += iter->bytes;
}
}else{
// current is not modified area
if(!prev_page.modified){
// previous is not modified area, too
prev_page.bytes += iter->bytes;
}else{
// previous is modified area
if(prev_page.bytes < MIN_MULTIPART_SIZE){
// previous(modified) area is too small for one multipart size,
// then part or all of current area is needed to download.
off_t missing_bytes = MIN_MULTIPART_SIZE - prev_page.bytes;
if((missing_bytes + MIN_MULTIPART_SIZE) < iter-> bytes){
// The current size is larger than the missing size, and the remainder
// after deducting the missing size is larger than the minimum size.
fdpage missing_page(iter->offset, missing_bytes, false, false);
download_pages.push_back(missing_page);
// previous(not modified) area is set upload area.
prev_page.bytes = MIN_MULTIPART_SIZE;
mixupload_pages.push_back(prev_page);
// set current to previous
prev_page = *iter;
prev_page.offset += missing_bytes;
prev_page.bytes -= missing_bytes;
}else{
// The current size is less than the missing size, or the remaining
// size less the missing size is less than the minimum size.
download_pages.push_back(*iter);
// add current to previous
prev_page.bytes += iter->bytes;
}
}else{
// previous(modified) area is enough size for one multipart size.
mixupload_pages.push_back(prev_page);
// set current to previous
prev_page = *iter;
}
}
}
}
// last area
if(0 < prev_page.bytes){
mixupload_pages.push_back(prev_page);
}
// compress
dlpages = compress_fdpage_list_ignore_modify(download_pages, false);
mixuppages = compress_fdpage_list_ignore_load(mixupload_pages, false);
// parse by max pagesize
dlpages = parse_partsize_fdpage_list(dlpages, max_partsize);
mixuppages = parse_partsize_fdpage_list(mixuppages, max_partsize);
return true;
}
bool PageList::GetNoDataPageLists(fdpage_list_t& nodata_pages, off_t start, size_t size)
{
// compress before this processing
if(!Compress()){
return false;
}
// extract areas without data
fdpage_list_t tmp_pagelist;
off_t stop_pos = (0L == size ? -1 : (start + size));
for(fdpage_list_t::const_iterator iter = pages.begin(); iter != pages.end(); ++iter){
if((iter->offset + iter->bytes) < start){
continue;
}
if(-1 != stop_pos && stop_pos <= iter->offset){
break;
}
if(iter->modified){
continue;
}
fdpage tmppage;
tmppage.offset = std::max(iter->offset, start);
tmppage.bytes = (-1 != stop_pos ? iter->bytes : std::min(iter->bytes, (stop_pos - tmppage.offset)));
tmppage.loaded = iter->loaded;
tmppage.modified = iter->modified;
tmp_pagelist.push_back(tmppage);
}
if(tmp_pagelist.empty()){
nodata_pages.clear();
}else{
// compress
nodata_pages = compress_fdpage_list(tmp_pagelist);
}
return true;
}
off_t PageList::BytesModified() const
{
off_t total = 0;
for(fdpage_list_t::const_iterator iter = pages.begin(); iter != pages.end(); ++iter){
if(iter->modified){
total += iter->bytes;
}
}
return total;
}
bool PageList::IsModified() const
{
for(fdpage_list_t::const_iterator iter = pages.begin(); iter != pages.end(); ++iter){
if(iter->modified){
return true;
}
}
return false;
}
bool PageList::ClearAllModified()
{
for(fdpage_list_t::iterator iter = pages.begin(); iter != pages.end(); ++iter){
if(iter->modified){
iter->modified = false;
}
}
return Compress();
}
bool PageList::Serialize(CacheFileStat& file, bool is_output, ino_t inode)
{
if(!file.Open()){
return false;
}
if(is_output){
//
// put to file
//
std::ostringstream ssall;
ssall << inode << ":" << Size();
for(fdpage_list_t::iterator iter = pages.begin(); iter != pages.end(); ++iter){
ssall << "\n" << iter->offset << ":" << iter->bytes << ":" << (iter->loaded ? "1" : "0") << ":" << (iter->modified ? "1" : "0");
}
if(-1 == ftruncate(file.GetFd(), 0)){
S3FS_PRN_ERR("failed to truncate file(to 0) for stats(%d)", errno);
return false;
}
std::string strall = ssall.str();
if(0 >= pwrite(file.GetFd(), strall.c_str(), strall.length(), 0)){
S3FS_PRN_ERR("failed to write stats(%d)", errno);
return false;
}
}else{
//
// loading from file
//
struct stat st;
memset(&st, 0, sizeof(struct stat));
if(-1 == fstat(file.GetFd(), &st)){
S3FS_PRN_ERR("fstat is failed. errno(%d)", errno);
return false;
}
if(0 >= st.st_size){
// nothing
Init(0, false, false);
return true;
}
char* ptmp = new char[st.st_size + 1];
ssize_t result;
// read from file
if(0 >= (result = pread(file.GetFd(), ptmp, st.st_size, 0))){
S3FS_PRN_ERR("failed to read stats(%d)", errno);
delete[] ptmp;
return false;
}
ptmp[result] = '\0';
std::string oneline;
std::istringstream ssall(ptmp);
// loaded
Clear();
// load head line(for size and inode)
off_t total;
ino_t cache_inode; // if this value is 0, it means old format.
if(!getline(ssall, oneline, '\n')){
S3FS_PRN_ERR("failed to parse stats.");
delete[] ptmp;
return false;
}else{
std::istringstream sshead(oneline);
std::string strhead1;
std::string strhead2;
// get first part in head line.
if(!getline(sshead, strhead1, ':')){
S3FS_PRN_ERR("failed to parse stats.");
delete[] ptmp;
return false;
}
// get second part in head line.
if(!getline(sshead, strhead2, ':')){
// old head format is "<size>\n"
total = cvt_strtoofft(strhead1.c_str(), /* base= */10);
cache_inode = 0;
}else{
// current head format is "<inode>:<size>\n"
total = cvt_strtoofft(strhead2.c_str(), /* base= */10);
cache_inode = static_cast<ino_t>(cvt_strtoofft(strhead1.c_str(), /* base= */10));
if(0 == cache_inode){
S3FS_PRN_ERR("wrong inode number in parsed cache stats.");
delete[] ptmp;
return false;
}
}
}
// check inode number
if(0 != cache_inode && cache_inode != inode){
S3FS_PRN_ERR("differ inode and inode number in parsed cache stats.");
delete[] ptmp;
return false;
}
// load each part
bool is_err = false;
while(getline(ssall, oneline, '\n')){
std::string part;
std::istringstream ssparts(oneline);
// offset
if(!getline(ssparts, part, ':')){
is_err = true;
break;
}
off_t offset = cvt_strtoofft(part.c_str(), /* base= */10);
// size
if(!getline(ssparts, part, ':')){
is_err = true;
break;
}
off_t size = cvt_strtoofft(part.c_str(), /* base= */10);
// loaded
if(!getline(ssparts, part, ':')){
is_err = true;
break;
}
bool is_loaded = (1 == cvt_strtoofft(part.c_str(), /* base= */10) ? true : false);
bool is_modified;
if(!getline(ssparts, part, ':')){
is_modified = false; // old version does not have this part.
}else{
is_modified = (1 == cvt_strtoofft(part.c_str(), /* base= */10) ? true : false);
}
// add new area
PageList::page_status pstatus =
( is_loaded && is_modified ? PageList::PAGE_LOAD_MODIFIED :
!is_loaded && is_modified ? PageList::PAGE_MODIFIED :
is_loaded && !is_modified ? PageList::PAGE_LOADED : PageList::PAGE_NOT_LOAD_MODIFIED );
SetPageLoadedStatus(offset, size, pstatus);
}
delete[] ptmp;
if(is_err){
S3FS_PRN_ERR("failed to parse stats.");
Clear();
return false;
}
// check size
if(total != Size()){
S3FS_PRN_ERR("different size(%lld - %lld).", static_cast<long long int>(total), static_cast<long long int>(Size()));
Clear();
return false;
}
}
return true;
}
void PageList::Dump() const
{
int cnt = 0;
S3FS_PRN_DBG("pages = {");
for(fdpage_list_t::const_iterator iter = pages.begin(); iter != pages.end(); ++iter, ++cnt){
S3FS_PRN_DBG(" [%08d] -> {%014lld - %014lld : %s / %s}", cnt, static_cast<long long int>(iter->offset), static_cast<long long int>(iter->bytes), iter->loaded ? "loaded" : "unloaded", iter->modified ? "modified" : "not modified");
}
S3FS_PRN_DBG("}");
}
//
// Compare the fdpage_list_t pages of the object with the state of the file.
//
// The loaded=true or modified=true area of pages must be a DATA block
// (not a HOLE block) in the file.
// The other area is a HOLE block in the file or is a DATA block(but the
// data of the target area in that block should be ZERO).
// If it is a bad area in the previous case, it will be reported as an error.
// If the latter case does not match, it will be reported as a warning.
//
bool PageList::CompareSparseFile(int fd, size_t file_size, fdpage_list_t& err_area_list, fdpage_list_t& warn_area_list)
{
err_area_list.clear();
warn_area_list.clear();
// First, list the block disk allocation area of the cache file.
// The cache file has holes(sparse file) and no disk block areas
// are assigned to any holes.
fdpage_list_t sparse_list;
if(!PageList::GetSparseFilePages(fd, file_size, sparse_list)){
S3FS_PRN_ERR("Something error is occurred in parsing hole/data of the cache file(physical_fd=%d).", fd);
fdpage page(0, static_cast<off_t>(file_size), false, false);
err_area_list.push_back(page);
return false;
}
if(sparse_list.empty() && pages.empty()){
// both file and stats information are empty, it means cache file size is ZERO.
return true;
}
// Compare each pages and sparse_list
bool result = true;
for(fdpage_list_t::const_iterator iter = pages.begin(); iter != pages.end(); ++iter){
if(!PageList::CheckAreaInSparseFile(*iter, sparse_list, fd, err_area_list, warn_area_list)){
result = false;
}
}
return result;
}
/*
* 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
*/

135
src/fdcache_page.h Normal file
View File

@ -0,0 +1,135 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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.
*/
#ifndef S3FS_FDCACHE_PAGE_H_
#define S3FS_FDCACHE_PAGE_H_
#include <list>
#include <sys/types.h>
#include "fdcache_stat.h"
//------------------------------------------------
// Symbols
//------------------------------------------------
// [NOTE]
// If the following symbols in lseek whence are undefined, define them.
// If it is not supported by lseek, s3fs judges by the processing result of lseek.
//
#ifndef SEEK_DATA
#define SEEK_DATA 3
#endif
#ifndef SEEK_HOLE
#define SEEK_HOLE 4
#endif
//------------------------------------------------
// Structure fdpage
//------------------------------------------------
// page block information
struct fdpage
{
off_t offset;
off_t bytes;
bool loaded;
bool modified;
fdpage(off_t start = 0, off_t size = 0, bool is_loaded = false, bool is_modified = false) :
offset(start), bytes(size), loaded(is_loaded), modified(is_modified) {}
off_t next() const
{
return (offset + bytes);
}
off_t end() const
{
return (0 < bytes ? offset + bytes - 1 : 0);
}
};
typedef std::list<struct fdpage> fdpage_list_t;
//------------------------------------------------
// Class PageList
//------------------------------------------------
class FdEntity;
// cppcheck-suppress copyCtorAndEqOperator
class PageList
{
friend class FdEntity; // only one method access directly pages.
private:
fdpage_list_t pages;
public:
enum page_status{
PAGE_NOT_LOAD_MODIFIED = 0,
PAGE_LOADED,
PAGE_MODIFIED,
PAGE_LOAD_MODIFIED
};
private:
static bool GetSparseFilePages(int fd, size_t file_size, fdpage_list_t& sparse_list);
static bool CheckZeroAreaInFile(int fd, off_t start, size_t bytes);
static bool CheckAreaInSparseFile(const struct fdpage& checkpage, const fdpage_list_t& sparse_list, int fd, fdpage_list_t& err_area_list, fdpage_list_t& warn_area_list);
void Clear();
bool Parse(off_t new_pos);
public:
static void FreeList(fdpage_list_t& list);
explicit PageList(off_t size = 0, bool is_loaded = false, bool is_modified = false);
explicit PageList(const PageList& other);
~PageList();
bool Init(off_t size, bool is_loaded, bool is_modified);
off_t Size() const;
bool Resize(off_t size, bool is_loaded, bool is_modified);
bool IsPageLoaded(off_t start = 0, off_t size = 0) const; // size=0 is checking to end of list
bool SetPageLoadedStatus(off_t start, off_t size, PageList::page_status pstatus = PAGE_LOADED, bool is_compress = true);
bool FindUnloadedPage(off_t start, off_t& resstart, off_t& ressize) const;
off_t GetTotalUnloadedPageSize(off_t start = 0, off_t size = 0, off_t limit_size = 0) const; // size=0 is checking to end of list
size_t GetUnloadedPages(fdpage_list_t& unloaded_list, off_t start = 0, off_t size = 0) const; // size=0 is checking to end of list
bool GetPageListsForMultipartUpload(fdpage_list_t& dlpages, fdpage_list_t& mixuppages, off_t max_partsize);
bool GetNoDataPageLists(fdpage_list_t& nodata_pages, off_t start = 0, size_t size = 0);
off_t BytesModified() const;
bool IsModified() const;
bool ClearAllModified();
bool Compress();
bool Serialize(CacheFileStat& file, bool is_output, ino_t inode);
void Dump() const;
bool CompareSparseFile(int fd, size_t file_size, fdpage_list_t& err_area_list, fdpage_list_t& warn_area_list);
};
#endif // S3FS_FDCACHE_PAGE_H_
/*
* 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
*/

134
src/fdcache_pseudofd.cpp Normal file
View File

@ -0,0 +1,134 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Takeshi Nakatani <ggtakec.com>
*
* 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 <cstdio>
#include <cstdlib>
#include <algorithm>
#include "common.h"
#include "s3fs.h"
#include "fdcache_pseudofd.h"
#include "autolock.h"
//------------------------------------------------
// Symbols
//------------------------------------------------
// [NOTE]
// The minimum pseudo fd value starts 2.
// This is to avoid mistakes for 0(stdout) and 1(stderr), which are usually used.
//
#define MIN_PSEUDOFD_NUMBER 2
//------------------------------------------------
// PseudoFdManager class methods
//------------------------------------------------
PseudoFdManager& PseudoFdManager::GetManager()
{
static PseudoFdManager singleton;
return singleton;
}
int PseudoFdManager::Get()
{
return (PseudoFdManager::GetManager()).CreatePseudoFd();
}
bool PseudoFdManager::Release(int fd)
{
return (PseudoFdManager::GetManager()).ReleasePseudoFd(fd);
}
//------------------------------------------------
// PseudoFdManager methods
//------------------------------------------------
PseudoFdManager::PseudoFdManager() : is_lock_init(false)
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
#if S3FS_PTHREAD_ERRORCHECK
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
#endif
int result;
if(0 != (result = pthread_mutex_init(&pseudofd_list_lock, &attr))){
S3FS_PRN_CRIT("failed to init pseudofd_list_lock: %d", result);
abort();
}
is_lock_init = true;
}
PseudoFdManager::~PseudoFdManager()
{
if(is_lock_init){
int result;
if(0 != (result = pthread_mutex_destroy(&pseudofd_list_lock))){
S3FS_PRN_CRIT("failed to destroy pseudofd_list_lock: %d", result);
abort();
}
is_lock_init = false;
}
}
int PseudoFdManager::GetUnusedMinPseudoFd() const
{
int min_fd = MIN_PSEUDOFD_NUMBER;
// Look for the first discontinuous value.
for(pseudofd_list_t::const_iterator iter = pseudofd_list.begin(); iter != pseudofd_list.end(); ++iter){
if(min_fd == (*iter)){
++min_fd;
}else if(min_fd < (*iter)){
break;
}
}
return min_fd;
}
int PseudoFdManager::CreatePseudoFd()
{
AutoLock auto_lock(&pseudofd_list_lock);
int new_fd = PseudoFdManager::GetUnusedMinPseudoFd();
pseudofd_list.push_back(new_fd);
std::sort(pseudofd_list.begin(), pseudofd_list.end());
return new_fd;
}
bool PseudoFdManager::ReleasePseudoFd(int fd)
{
AutoLock auto_lock(&pseudofd_list_lock);
for(pseudofd_list_t::iterator iter = pseudofd_list.begin(); iter != pseudofd_list.end(); ++iter){
if(fd == (*iter)){
pseudofd_list.erase(iter);
return true;
}
}
return false;
}
/*
* 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
*/

65
src/fdcache_pseudofd.h Normal file
View File

@ -0,0 +1,65 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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.
*/
#ifndef S3FS_FDCACHE_PSEUDOFD_H_
#define S3FS_FDCACHE_PSEUDOFD_H_
//------------------------------------------------
// Typdefs
//------------------------------------------------
// List of pseudo fd in use
//
typedef std::vector<int> pseudofd_list_t;
//------------------------------------------------
// Class PseudoFdManager
//------------------------------------------------
class PseudoFdManager
{
private:
pseudofd_list_t pseudofd_list;
bool is_lock_init;
pthread_mutex_t pseudofd_list_lock; // protects pseudofd_list
private:
static PseudoFdManager& GetManager();
PseudoFdManager();
~PseudoFdManager();
int GetUnusedMinPseudoFd() const;
int CreatePseudoFd();
bool ReleasePseudoFd(int fd);
public:
static int Get();
static bool Release(int fd);
};
#endif // S3FS_FDCACHE_PSEUDOFD_H_
/*
* 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
*/

280
src/fdcache_stat.cpp Normal file
View File

@ -0,0 +1,280 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Takeshi Nakatani <ggtakec.com>
*
* 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 <cstdio>
#include <cstdlib>
#include <cerrno>
#include <unistd.h>
#include <sys/file.h>
#include "common.h"
#include "s3fs.h"
#include "fdcache_stat.h"
#include "fdcache.h"
#include "s3fs_util.h"
#include "string_util.h"
//------------------------------------------------
// CacheFileStat class methods
//------------------------------------------------
std::string CacheFileStat::GetCacheFileStatTopDir()
{
std::string top_path;
if(!FdManager::IsCacheDir() || bucket.empty()){
return top_path;
}
// stat top dir( "/<cache_dir>/.<bucket_name>.stat" )
top_path += FdManager::GetCacheDir();
top_path += "/.";
top_path += bucket;
top_path += ".stat";
return top_path;
}
bool CacheFileStat::MakeCacheFileStatPath(const char* path, std::string& sfile_path, bool is_create_dir)
{
std::string top_path = CacheFileStat::GetCacheFileStatTopDir();
if(top_path.empty()){
S3FS_PRN_ERR("The path to cache top dir is empty.");
return false;
}
if(is_create_dir){
int result;
if(0 != (result = mkdirp(top_path + mydirname(path), 0777))){
S3FS_PRN_ERR("failed to create dir(%s) by errno(%d).", path, result);
return false;
}
}
if(!path || '\0' == path[0]){
sfile_path = top_path;
}else{
sfile_path = top_path + SAFESTRPTR(path);
}
return true;
}
bool CacheFileStat::CheckCacheFileStatTopDir()
{
std::string top_path = CacheFileStat::GetCacheFileStatTopDir();
if(top_path.empty()){
S3FS_PRN_INFO("The path to cache top dir is empty, thus not need to check permission.");
return true;
}
return check_exist_dir_permission(top_path.c_str());
}
bool CacheFileStat::DeleteCacheFileStat(const char* path)
{
if(!path || '\0' == path[0]){
return false;
}
// stat path
std::string sfile_path;
if(!CacheFileStat::MakeCacheFileStatPath(path, sfile_path, false)){
S3FS_PRN_ERR("failed to create cache stat file path(%s)", path);
return false;
}
if(0 != unlink(sfile_path.c_str())){
if(ENOENT == errno){
S3FS_PRN_DBG("failed to delete file(%s): errno=%d", path, errno);
}else{
S3FS_PRN_ERR("failed to delete file(%s): errno=%d", path, errno);
}
return false;
}
return true;
}
// [NOTE]
// If remove stat file directory, it should do before removing
// file cache directory.
//
bool CacheFileStat::DeleteCacheFileStatDirectory()
{
std::string top_path = CacheFileStat::GetCacheFileStatTopDir();
if(top_path.empty()){
S3FS_PRN_INFO("The path to cache top dir is empty, thus not need to remove it.");
return true;
}
return delete_files_in_dir(top_path.c_str(), true);
}
bool CacheFileStat::RenameCacheFileStat(const char* oldpath, const char* newpath)
{
if(!oldpath || '\0' == oldpath[0] || !newpath || '\0' == newpath[0]){
return false;
}
// stat path
std::string old_filestat;
std::string new_filestat;
if(!CacheFileStat::MakeCacheFileStatPath(oldpath, old_filestat, false) || !CacheFileStat::MakeCacheFileStatPath(newpath, new_filestat, false)){
return false;
}
// check new stat path
struct stat st;
if(0 == stat(new_filestat.c_str(), &st)){
// new stat path is existed, then unlink it.
if(-1 == unlink(new_filestat.c_str())){
S3FS_PRN_ERR("failed to unlink new cache file stat path(%s) by errno(%d).", new_filestat.c_str(), errno);
return false;
}
}
// check old stat path
if(0 != stat(old_filestat.c_str(), &st)){
// old stat path is not existed, then nothing to do any more.
return true;
}
// link and unlink
if(-1 == link(old_filestat.c_str(), new_filestat.c_str())){
S3FS_PRN_ERR("failed to link old cache file stat path(%s) to new cache file stat path(%s) by errno(%d).", old_filestat.c_str(), new_filestat.c_str(), errno);
return false;
}
if(-1 == unlink(old_filestat.c_str())){
S3FS_PRN_ERR("failed to unlink old cache file stat path(%s) by errno(%d).", old_filestat.c_str(), errno);
return false;
}
return true;
}
//------------------------------------------------
// CacheFileStat methods
//------------------------------------------------
CacheFileStat::CacheFileStat(const char* tpath) : fd(-1)
{
if(tpath && '\0' != tpath[0]){
SetPath(tpath, true);
}
}
CacheFileStat::~CacheFileStat()
{
Release();
}
bool CacheFileStat::SetPath(const char* tpath, bool is_open)
{
if(!tpath || '\0' == tpath[0]){
return false;
}
if(!Release()){
// could not close old stat file.
return false;
}
path = tpath;
if(!is_open){
return true;
}
return Open();
}
bool CacheFileStat::RawOpen(bool readonly)
{
if(path.empty()){
return false;
}
if(-1 != fd){
// already opened
return true;
}
// stat path
std::string sfile_path;
if(!CacheFileStat::MakeCacheFileStatPath(path.c_str(), sfile_path, true)){
S3FS_PRN_ERR("failed to create cache stat file path(%s)", path.c_str());
return false;
}
// open
if(readonly){
if(-1 == (fd = open(sfile_path.c_str(), O_RDONLY))){
S3FS_PRN_ERR("failed to read only open cache stat file path(%s) - errno(%d)", path.c_str(), errno);
return false;
}
}else{
if(-1 == (fd = open(sfile_path.c_str(), O_CREAT|O_RDWR, 0600))){
S3FS_PRN_ERR("failed to open cache stat file path(%s) - errno(%d)", path.c_str(), errno);
return false;
}
}
// lock
if(-1 == flock(fd, LOCK_EX)){
S3FS_PRN_ERR("failed to lock cache stat file(%s) - errno(%d)", path.c_str(), errno);
close(fd);
fd = -1;
return false;
}
// seek top
if(0 != lseek(fd, 0, SEEK_SET)){
S3FS_PRN_ERR("failed to lseek cache stat file(%s) - errno(%d)", path.c_str(), errno);
flock(fd, LOCK_UN);
close(fd);
fd = -1;
return false;
}
S3FS_PRN_DBG("file locked(%s - %s)", path.c_str(), sfile_path.c_str());
return true;
}
bool CacheFileStat::Open()
{
return RawOpen(false);
}
bool CacheFileStat::ReadOnlyOpen()
{
return RawOpen(true);
}
bool CacheFileStat::Release()
{
if(-1 == fd){
// already release
return true;
}
// unlock
if(-1 == flock(fd, LOCK_UN)){
S3FS_PRN_ERR("failed to unlock cache stat file(%s) - errno(%d)", path.c_str(), errno);
return false;
}
S3FS_PRN_DBG("file unlocked(%s)", path.c_str());
if(-1 == close(fd)){
S3FS_PRN_ERR("failed to close cache stat file(%s) - errno(%d)", path.c_str(), errno);
return false;
}
fd = -1;
return true;
}
/*
* 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
*/

64
src/fdcache_stat.h Normal file
View File

@ -0,0 +1,64 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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.
*/
#ifndef S3FS_FDCACHE_STAT_H_
#define S3FS_FDCACHE_STAT_H_
//------------------------------------------------
// CacheFileStat
//------------------------------------------------
class CacheFileStat
{
private:
std::string path;
int fd;
private:
static bool MakeCacheFileStatPath(const char* path, std::string& sfile_path, bool is_create_dir = true);
bool RawOpen(bool readonly);
public:
static std::string GetCacheFileStatTopDir();
static bool DeleteCacheFileStat(const char* path);
static bool CheckCacheFileStatTopDir();
static bool DeleteCacheFileStatDirectory();
static bool RenameCacheFileStat(const char* oldpath, const char* newpath);
explicit CacheFileStat(const char* tpath = NULL);
~CacheFileStat();
bool Open();
bool ReadOnlyOpen();
bool Release();
bool SetPath(const char* tpath, bool is_open = true);
int GetFd() const { return fd; }
};
#endif // S3FS_FDCACHE_STAT_H_
/*
* 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
*/

284
src/fdcache_untreated.cpp Normal file
View File

@ -0,0 +1,284 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Takeshi Nakatani <ggtakec.com>
*
* 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 <cstdio>
#include <cstdlib>
#include <algorithm>
#include "common.h"
#include "s3fs.h"
#include "fdcache_untreated.h"
#include "autolock.h"
//------------------------------------------------
// UntreatedParts methods
//------------------------------------------------
UntreatedParts::UntreatedParts() : last_tag(0) //, is_lock_init(false)
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
#if S3FS_PTHREAD_ERRORCHECK
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
#endif
int result;
if(0 != (result = pthread_mutex_init(&untreated_list_lock, &attr))){
S3FS_PRN_CRIT("failed to init untreated_list_lock: %d", result);
abort();
}
is_lock_init = true;
}
UntreatedParts::~UntreatedParts()
{
if(is_lock_init){
int result;
if(0 != (result = pthread_mutex_destroy(&untreated_list_lock))){
S3FS_PRN_CRIT("failed to destroy untreated_list_lock: %d", result);
abort();
}
is_lock_init = false;
}
}
bool UntreatedParts::empty()
{
AutoLock auto_lock(&untreated_list_lock);
return untreated_list.empty();
}
bool UntreatedParts::AddPart(off_t start, off_t size)
{
if(start < 0 || size <= 0){
S3FS_PRN_ERR("Paramter are wrong(start=%lld, size=%lld).", static_cast<long long int>(start), static_cast<long long int>(size));
return false;
}
AutoLock auto_lock(&untreated_list_lock);
++last_tag;
// Check the overlap with the existing part and add the part.
for(untreated_list_t::iterator iter = untreated_list.begin(); iter != untreated_list.end(); ++iter){
if(iter->stretch(start, size, last_tag)){
// the part was stretched, thus check if it overlaps with next parts
untreated_list_t::iterator niter = iter;
for(++niter; niter != untreated_list.end(); ){
if(!iter->stretch(niter->start, niter->size, last_tag)){
// This next part does not overlap with the current part
break;
}
// Since the parts overlap and the current part is stretched, delete this next part.
niter = untreated_list.erase(niter);
}
// success to stretch and compress existed parts
return true;
}else if((start + size) < iter->start){
// The part to add should be inserted before the current part.
untreated_list.insert(iter, untreatedpart(start, size, last_tag));
return true;
}
}
// There are no overlapping parts in the untreated_list, then add the part at end of list
untreated_list.push_back(untreatedpart(start, size, last_tag));
return true;
}
bool UntreatedParts::RowGetPart(off_t& start, off_t& size, off_t max_size, off_t min_size, bool lastpart)
{
if(max_size <= 0 || min_size < 0 || max_size < min_size){
S3FS_PRN_ERR("Paramter are wrong(max_size=%lld, min_size=%lld).", static_cast<long long int>(max_size), static_cast<long long int>(min_size));
return false;
}
AutoLock auto_lock(&untreated_list_lock);
// Check the overlap with the existing part and add the part.
for(untreated_list_t::iterator iter = untreated_list.begin(); iter != untreated_list.end(); ++iter){
if(!lastpart || iter->untreated_tag == last_tag){
if(min_size <= iter->size){
if(iter->size <= max_size){
// whole part( min <= part size <= max )
start = iter->start;
size = iter->size;
}else{
// Partially take out part( max < part size )
start = iter->start;
size = max_size;
}
return true;
}else{
if(lastpart){
return false;
}
}
}
}
return false;
}
// [NOTE]
// The part with the last tag cannot be taken out if it has not reached max_size.
//
bool UntreatedParts::TakeoutPart(off_t& start, off_t& size, off_t max_size, off_t min_size)
{
if(max_size <= 0 || min_size < 0 || max_size < min_size){
S3FS_PRN_ERR("Paramter are wrong(max_size=%lld, min_size=%lld).", static_cast<long long int>(max_size), static_cast<long long int>(min_size));
return false;
}
AutoLock auto_lock(&untreated_list_lock);
// Check the overlap with the existing part and add the part.
for(untreated_list_t::iterator iter = untreated_list.begin(); iter != untreated_list.end(); ++iter){
if(iter->untreated_tag == last_tag){
// Last updated part
if(max_size <= iter->size){
// Take out only when the maximum part size is exceeded
start = iter->start;
size = max_size;
iter->start = iter->start + max_size;
iter->size = iter->size - max_size;
if(iter->size == 0){
untreated_list.erase(iter);
}
return true;
}
}else{
// Parts updated in the past
if(min_size <= iter->size){
if(iter->size <= max_size){
// Take out the whole part( min <= part size <= max )
start = iter->start;
size = iter->size;
untreated_list.erase(iter);
}else{
// Partially take out part( max < part size )
start = iter->start;
size = max_size;
iter->start = iter->start + max_size;
iter->size = iter->size - max_size;
}
return true;
}
}
}
return false;
}
// [NOTE]
// This method returns the part from the beginning, ignoring conditions
// such as whether it is being updated(the last updated part) or less
// than the minimum size.
//
bool UntreatedParts::TakeoutPartFromBegin(off_t& start, off_t& size, off_t max_size)
{
if(max_size <= 0){
S3FS_PRN_ERR("Paramter is wrong(max_size=%lld).", static_cast<long long int>(max_size));
return false;
}
AutoLock auto_lock(&untreated_list_lock);
if(untreated_list.empty()){
return false;
}
untreated_list_t::iterator iter = untreated_list.begin();
if(iter->size <= max_size){
// Take out the whole part( part size <= max )
start = iter->start;
size = iter->size;
untreated_list.erase(iter);
}else{
// Take out only when the maximum part size is exceeded
start = iter->start;
size = max_size;
iter->start = iter->start + max_size;
iter->size = iter->size - max_size;
}
return true;
}
// [NOTE]
// If size is specified as 0, all areas(parts) after start will be deleted.
//
bool UntreatedParts::ClearParts(off_t start, off_t size)
{
if(start < 0 || size < 0){
S3FS_PRN_ERR("Paramter are wrong(start=%lld, size=%lld).", static_cast<long long int>(start), static_cast<long long int>(size));
return false;
}
AutoLock auto_lock(&untreated_list_lock);
if(untreated_list.empty()){
return true;
}
// Check the overlap with the existing part.
for(untreated_list_t::iterator iter = untreated_list.begin(); iter != untreated_list.end(); ){
if(0 != size && (start + size) <= iter->start){
// clear area is in front of iter area, no more to do.
break;
}else if(start <= iter->start){
if(0 != size && (start + size) <= (iter->start + iter->size)){
// clear area overlaps with iter area(on the start side)
iter->size = (iter->start + iter->size) - (start + size);
iter->start = start + size;
if(0 == iter->size){
iter = untreated_list.erase(iter);
}
}else{
// clear area overlaps with all of iter area
iter = untreated_list.erase(iter);
}
}else if(start < (iter->start + iter->size)){
// clear area overlaps with iter area(on the end side)
if(0 == size || (iter->start + iter->size) <= (start + size) ){
// start to iter->end is clear
iter->size = start - iter->start;
}else{
// parse current part
iter->size = start - iter->start;
// add new part
off_t next_start = start + size;
off_t next_size = (iter->start + iter->size) - (start + size);
long next_tag = iter->untreated_tag;
++iter;
iter = untreated_list.insert(iter, untreatedpart(next_start, next_size, next_tag));
++iter;
}
}else{
// clear area is in behind of iter area
++iter;
}
}
return true;
}
/*
* 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
*/

73
src/fdcache_untreated.h Normal file
View File

@ -0,0 +1,73 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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.
*/
#ifndef S3FS_FDCACHE_UNTREATED_H_
#define S3FS_FDCACHE_UNTREATED_H_
#include "common.h"
#include "types.h"
//------------------------------------------------
// Class UntreatedParts
//------------------------------------------------
class UntreatedParts
{
private:
pthread_mutex_t untreated_list_lock; // protects untreated_list
bool is_lock_init;
untreated_list_t untreated_list;
long last_tag; // [NOTE] Use this to identify the latest updated part.
private:
bool RowGetPart(off_t& start, off_t& size, off_t max_size, off_t min_size, bool lastpart);
public:
UntreatedParts();
~UntreatedParts();
bool empty();
bool AddPart(off_t start, off_t size);
// [NOTE]
// The following method does not return parts smaller than mini_size.
// You can avoid it by setting min_size to 0.
//
bool GetPart(off_t& start, off_t& size, off_t max_size, off_t min_size = MIN_MULTIPART_SIZE) { return RowGetPart(start, size, max_size, min_size, false); }
bool GetLastUpdatedPart(off_t& start, off_t& size, off_t max_size, off_t min_size = MIN_MULTIPART_SIZE) { return RowGetPart(start, size, max_size, min_size, true); }
bool TakeoutPart(off_t& start, off_t& size, off_t max_size, off_t min_size = MIN_MULTIPART_SIZE);
bool TakeoutPartFromBegin(off_t& start, off_t& size, off_t max_size);
bool ClearParts(off_t start, off_t size);
bool ClearAll() { return ClearParts(0, 0); }
};
#endif // S3FS_FDCACHE_UNTREATED_H_
/*
* 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
*/

View File

@ -1,7 +1,7 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright 2007-2008 Randy Rizun <rrizun@gmail.com>
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -30,7 +30,7 @@
#include <gcrypt.h>
#include <gnutls/gnutls.h>
#include <gnutls/crypto.h>
#ifdef USE_GNUTLS_NETTLE
#ifdef USE_GNUTLS_NETTLE
#include <nettle/md5.h>
#include <nettle/sha1.h>
#include <nettle/hmac.h>
@ -39,228 +39,361 @@
#include <map>
#include "common.h"
#include "s3fs.h"
#include "s3fs_auth.h"
using namespace std;
//-------------------------------------------------------------------
// Utility Function for version
//-------------------------------------------------------------------
#ifdef USE_GNUTLS_NETTLE
#ifdef USE_GNUTLS_NETTLE
const char* s3fs_crypt_lib_name(void)
{
static const char version[] = "GnuTLS(nettle)";
static const char version[] = "GnuTLS(nettle)";
return version;
return version;
}
#else // USE_GNUTLS_NETTLE
#else // USE_GNUTLS_NETTLE
const char* s3fs_crypt_lib_name(void)
const char* s3fs_crypt_lib_name()
{
static const char version[] = "GnuTLS(gcrypt)";
static const char version[] = "GnuTLS(gcrypt)";
return version;
return version;
}
#endif // USE_GNUTLS_NETTLE
#endif // USE_GNUTLS_NETTLE
//-------------------------------------------------------------------
// Utility Function for global init
//-------------------------------------------------------------------
bool s3fs_init_global_ssl(void)
bool s3fs_init_global_ssl()
{
if(GNUTLS_E_SUCCESS != gnutls_global_init()){
return false;
}
return true;
if(GNUTLS_E_SUCCESS != gnutls_global_init()){
return false;
}
#ifndef USE_GNUTLS_NETTLE
if(NULL == gcry_check_version(NULL)){
return false;
}
#endif // USE_GNUTLS_NETTLE
return true;
}
bool s3fs_destroy_global_ssl(void)
bool s3fs_destroy_global_ssl()
{
gnutls_global_deinit();
return true;
gnutls_global_deinit();
return true;
}
//-------------------------------------------------------------------
// Utility Function for crypt lock
//-------------------------------------------------------------------
bool s3fs_init_crypt_mutex(void)
bool s3fs_init_crypt_mutex()
{
return true;
return true;
}
bool s3fs_destroy_crypt_mutex(void)
bool s3fs_destroy_crypt_mutex()
{
return true;
return true;
}
//-------------------------------------------------------------------
// Utility Function for HMAC
//-------------------------------------------------------------------
#ifdef USE_GNUTLS_NETTLE
#ifdef USE_GNUTLS_NETTLE
bool s3fs_HMAC(const void* key, size_t keylen, const unsigned char* data, size_t datalen, unsigned char** digest, unsigned int* digestlen)
{
if(!key || 0 >= keylen || !data || 0 >= datalen || !digest || !digestlen){
return false;
}
if(!key || !data || !digest || !digestlen){
return false;
}
if(NULL == (*digest = (unsigned char*)malloc(SHA1_DIGEST_SIZE))){
return false;
}
*digest = new unsigned char[SHA1_DIGEST_SIZE];
struct hmac_sha1_ctx ctx_hmac;
hmac_sha1_set_key(&ctx_hmac, keylen, reinterpret_cast<const uint8_t*>(key));
hmac_sha1_update(&ctx_hmac, datalen, reinterpret_cast<const uint8_t*>(data));
hmac_sha1_digest(&ctx_hmac, SHA1_DIGEST_SIZE, reinterpret_cast<uint8_t*>(*digest));
*digestlen = SHA1_DIGEST_SIZE;
struct hmac_sha1_ctx ctx_hmac;
hmac_sha1_set_key(&ctx_hmac, keylen, reinterpret_cast<const uint8_t*>(key));
hmac_sha1_update(&ctx_hmac, datalen, reinterpret_cast<const uint8_t*>(data));
hmac_sha1_digest(&ctx_hmac, SHA1_DIGEST_SIZE, reinterpret_cast<uint8_t*>(*digest));
*digestlen = SHA1_DIGEST_SIZE;
return true;
return true;
}
#else // USE_GNUTLS_NETTLE
bool s3fs_HMAC256(const void* key, size_t keylen, const unsigned char* data, size_t datalen, unsigned char** digest, unsigned int* digestlen)
{
if(!key || !data || !digest || !digestlen){
return false;
}
*digest = new unsigned char[SHA256_DIGEST_SIZE];
struct hmac_sha256_ctx ctx_hmac;
hmac_sha256_set_key(&ctx_hmac, keylen, reinterpret_cast<const uint8_t*>(key));
hmac_sha256_update(&ctx_hmac, datalen, reinterpret_cast<const uint8_t*>(data));
hmac_sha256_digest(&ctx_hmac, SHA256_DIGEST_SIZE, reinterpret_cast<uint8_t*>(*digest));
*digestlen = SHA256_DIGEST_SIZE;
return true;
}
#else // USE_GNUTLS_NETTLE
bool s3fs_HMAC(const void* key, size_t keylen, const unsigned char* data, size_t datalen, unsigned char** digest, unsigned int* digestlen)
{
if(!key || 0 >= keylen || !data || 0 >= datalen || !digest || !digestlen){
return false;
}
if(!key || !data || !digest || !digestlen){
return false;
}
if(0 >= (*digestlen = gnutls_hmac_get_len(GNUTLS_MAC_SHA1))){
return false;
}
if(NULL == (*digest = (unsigned char*)malloc(*digestlen + 1))){
return false;
}
if(0 > gnutls_hmac_fast(GNUTLS_MAC_SHA1, key, keylen, data, datalen, *digest)){
free(*digest);
*digest = NULL;
return false;
}
return true;
if(0 == (*digestlen = gnutls_hmac_get_len(GNUTLS_MAC_SHA1))){
return false;
}
*digest = new unsigned char[*digestlen + 1];
if(0 > gnutls_hmac_fast(GNUTLS_MAC_SHA1, key, keylen, data, datalen, *digest)){
delete[] *digest;
*digest = NULL;
return false;
}
return true;
}
#endif // USE_GNUTLS_NETTLE
bool s3fs_HMAC256(const void* key, size_t keylen, const unsigned char* data, size_t datalen, unsigned char** digest, unsigned int* digestlen)
{
if(!key || !data || !digest || !digestlen){
return false;
}
if(0 == (*digestlen = gnutls_hmac_get_len(GNUTLS_MAC_SHA256))){
return false;
}
*digest = new unsigned char[*digestlen + 1];
if(0 > gnutls_hmac_fast(GNUTLS_MAC_SHA256, key, keylen, data, datalen, *digest)){
delete[] *digest;
*digest = NULL;
return false;
}
return true;
}
#endif // USE_GNUTLS_NETTLE
//-------------------------------------------------------------------
// Utility Function for MD5
//-------------------------------------------------------------------
#define MD5_DIGEST_LENGTH 16
size_t get_md5_digest_length(void)
size_t get_md5_digest_length()
{
return MD5_DIGEST_LENGTH;
return 16;
}
#ifdef USE_GNUTLS_NETTLE
unsigned char* s3fs_md5hexsum(int fd, off_t start, ssize_t size)
#ifdef USE_GNUTLS_NETTLE
unsigned char* s3fs_md5_fd(int fd, off_t start, off_t size)
{
struct md5_ctx ctx_md5;
unsigned char buf[512];
ssize_t bytes;
unsigned char* result;
struct md5_ctx ctx_md5;
off_t bytes;
unsigned char* result;
// seek to top of file.
if(-1 == lseek(fd, start, SEEK_SET)){
return NULL;
}
memset(buf, 0, 512);
md5_init(&ctx_md5);
for(ssize_t total = 0; total < size; total += bytes){
bytes = 512 < (size - total) ? 512 : (size - total);
bytes = read(fd, buf, bytes);
if(0 == bytes){
// end of file
break;
}else if(-1 == bytes){
// error
DPRNNN("file read error(%d)", errno);
return NULL;
if(-1 == size){
struct stat st;
if(-1 == fstat(fd, &st)){
return NULL;
}
size = st.st_size;
}
md5_update(&ctx_md5, bytes, buf);
memset(buf, 0, 512);
}
if(NULL == (result = (unsigned char*)malloc(get_md5_digest_length()))){
return NULL;
}
md5_digest(&ctx_md5, get_md5_digest_length(), result);
if(-1 == lseek(fd, start, SEEK_SET)){
free(result);
return NULL;
}
md5_init(&ctx_md5);
return result;
for(off_t total = 0; total < size; total += bytes){
off_t len = 512;
unsigned char buf[len];
bytes = len < (size - total) ? len : (size - total);
bytes = pread(fd, buf, bytes, start + total);
if(0 == bytes){
// end of file
break;
}else if(-1 == bytes){
// error
S3FS_PRN_ERR("file read error(%d)", errno);
return NULL;
}
md5_update(&ctx_md5, bytes, buf);
}
result = new unsigned char[get_md5_digest_length()];
md5_digest(&ctx_md5, get_md5_digest_length(), result);
return result;
}
#else // USE_GNUTLS_NETTLE
#else // USE_GNUTLS_NETTLE
unsigned char* s3fs_md5hexsum(int fd, off_t start, ssize_t size)
unsigned char* s3fs_md5_fd(int fd, off_t start, off_t size)
{
gcry_md_hd_t ctx_md5;
gcry_error_t err;
char buf[512];
ssize_t bytes;
unsigned char* result;
gcry_md_hd_t ctx_md5;
gcry_error_t err;
off_t bytes;
unsigned char* result;
if(-1 == size){
struct stat st;
if(-1 == fstat(fd, &st)){
return NULL;
if(-1 == size){
struct stat st;
if(-1 == fstat(fd, &st)){
return NULL;
}
size = st.st_size;
}
size = static_cast<ssize_t>(st.st_size);
}
// seek to top of file.
if(-1 == lseek(fd, start, SEEK_SET)){
return NULL;
}
memset(buf, 0, 512);
if(GPG_ERR_NO_ERROR != (err = gcry_md_open(&ctx_md5, GCRY_MD_MD5, 0))){
DPRNN("MD5 context creation failure: %s/%s", gcry_strsource(err), gcry_strerror(err));
return NULL;
}
for(ssize_t total = 0; total < size; total += bytes){
bytes = 512 < (size - total) ? 512 : (size - total);
bytes = read(fd, buf, bytes);
if(0 == bytes){
// end of file
break;
}else if(-1 == bytes){
// error
DPRNNN("file read error(%d)", errno);
return NULL;
if(GPG_ERR_NO_ERROR != (err = gcry_md_open(&ctx_md5, GCRY_MD_MD5, 0))){
S3FS_PRN_ERR("MD5 context creation failure: %s/%s", gcry_strsource(err), gcry_strerror(err));
return NULL;
}
gcry_md_write(ctx_md5, buf, bytes);
memset(buf, 0, 512);
}
if(NULL == (result = (unsigned char*)malloc(get_md5_digest_length()))){
return NULL;
}
memcpy(result, gcry_md_read(ctx_md5, 0), get_md5_digest_length());
gcry_md_close(ctx_md5);
if(-1 == lseek(fd, start, SEEK_SET)){
free(result);
return NULL;
}
for(off_t total = 0; total < size; total += bytes){
off_t len = 512;
char buf[len];
bytes = len < (size - total) ? len : (size - total);
bytes = pread(fd, buf, bytes, start + total);
if(0 == bytes){
// end of file
break;
}else if(-1 == bytes){
// error
S3FS_PRN_ERR("file read error(%d)", errno);
gcry_md_close(ctx_md5);
return NULL;
}
gcry_md_write(ctx_md5, buf, bytes);
}
result = new unsigned char[get_md5_digest_length()];
memcpy(result, gcry_md_read(ctx_md5, 0), get_md5_digest_length());
gcry_md_close(ctx_md5);
return result;
return result;
}
#endif // USE_GNUTLS_NETTLE
#endif // USE_GNUTLS_NETTLE
//-------------------------------------------------------------------
// Utility Function for SHA256
//-------------------------------------------------------------------
size_t get_sha256_digest_length()
{
return 32;
}
#ifdef USE_GNUTLS_NETTLE
bool s3fs_sha256(const unsigned char* data, size_t datalen, unsigned char** digest, unsigned int* digestlen)
{
(*digestlen) = static_cast<unsigned int>(get_sha256_digest_length());
*digest = new unsigned char[*digestlen];
struct sha256_ctx ctx_sha256;
sha256_init(&ctx_sha256);
sha256_update(&ctx_sha256, datalen, data);
sha256_digest(&ctx_sha256, *digestlen, *digest);
return true;
}
unsigned char* s3fs_sha256_fd(int fd, off_t start, off_t size)
{
struct sha256_ctx ctx_sha256;
off_t bytes;
unsigned char* result;
sha256_init(&ctx_sha256);
for(off_t total = 0; total < size; total += bytes){
off_t len = 512;
unsigned char buf[len];
bytes = len < (size - total) ? len : (size - total);
bytes = pread(fd, buf, bytes, start + total);
if(0 == bytes){
// end of file
break;
}else if(-1 == bytes){
// error
S3FS_PRN_ERR("file read error(%d)", errno);
return NULL;
}
sha256_update(&ctx_sha256, bytes, buf);
}
result = new unsigned char[get_sha256_digest_length()];
sha256_digest(&ctx_sha256, get_sha256_digest_length(), result);
return result;
}
#else // USE_GNUTLS_NETTLE
bool s3fs_sha256(const unsigned char* data, size_t datalen, unsigned char** digest, unsigned int* digestlen)
{
size_t len = (*digestlen) = static_cast<unsigned int>(get_sha256_digest_length());
*digest = new unsigned char[len];
gcry_md_hd_t ctx_sha256;
gcry_error_t err;
if(GPG_ERR_NO_ERROR != (err = gcry_md_open(&ctx_sha256, GCRY_MD_SHA256, 0))){
S3FS_PRN_ERR("SHA256 context creation failure: %s/%s", gcry_strsource(err), gcry_strerror(err));
delete[] *digest;
return false;
}
gcry_md_write(ctx_sha256, data, datalen);
memcpy(*digest, gcry_md_read(ctx_sha256, 0), *digestlen);
gcry_md_close(ctx_sha256);
return true;
}
unsigned char* s3fs_sha256_fd(int fd, off_t start, off_t size)
{
gcry_md_hd_t ctx_sha256;
gcry_error_t err;
off_t bytes;
unsigned char* result;
if(-1 == size){
struct stat st;
if(-1 == fstat(fd, &st)){
return NULL;
}
size = st.st_size;
}
if(GPG_ERR_NO_ERROR != (err = gcry_md_open(&ctx_sha256, GCRY_MD_SHA256, 0))){
S3FS_PRN_ERR("SHA256 context creation failure: %s/%s", gcry_strsource(err), gcry_strerror(err));
return NULL;
}
for(off_t total = 0; total < size; total += bytes){
off_t len = 512;
char buf[len];
bytes = len < (size - total) ? len : (size - total);
bytes = pread(fd, buf, bytes, start + total);
if(0 == bytes){
// end of file
break;
}else if(-1 == bytes){
// error
S3FS_PRN_ERR("file read error(%d)", errno);
gcry_md_close(ctx_sha256);
return NULL;
}
gcry_md_write(ctx_sha256, buf, bytes);
}
result = new unsigned char[get_sha256_digest_length()];
memcpy(result, gcry_md_read(ctx_sha256, 0), get_sha256_digest_length());
gcry_md_close(ctx_sha256);
return result;
}
#endif // USE_GNUTLS_NETTLE
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
* vim600: expandtab sw=4 ts=4 fdm=marker
* vim<600: expandtab sw=4 ts=4
*/

336
src/metaheader.cpp Normal file
View File

@ -0,0 +1,336 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Takeshi Nakatani <ggtakec.com>
*
* 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 <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include "common.h"
#include "s3fs.h"
#include "metaheader.h"
#include "string_util.h"
//-------------------------------------------------------------------
// Utility functions for convert
//-------------------------------------------------------------------
static struct timespec cvt_string_to_time(const char *str)
{
// [NOTE]
// In rclone, there are cases where ns is set to x-amz-meta-mtime
// with floating point number. s3fs uses x-amz-meta-mtime by
// truncating the floating point or less (in seconds or less) to
// correspond to this.
//
std::string strmtime;
long nsec = 0;
if(str && '\0' != *str){
strmtime = str;
std::string::size_type pos = strmtime.find('.', 0);
if(std::string::npos != pos){
nsec = cvt_strtoofft(strmtime.substr(pos + 1).c_str(), /*base=*/ 10);
strmtime.erase(pos);
}
}
return {static_cast<time_t>(cvt_strtoofft(strmtime.c_str(), /*base=*/ 10)), nsec};
}
static struct timespec get_time(const headers_t& meta, const char *header)
{
headers_t::const_iterator iter;
if(meta.end() == (iter = meta.find(header))){
return {-1, 0};
}
return cvt_string_to_time((*iter).second.c_str());
}
struct timespec get_mtime(const headers_t& meta, bool overcheck)
{
struct timespec t = get_time(meta, "x-amz-meta-mtime");
if(0 < t.tv_sec){
return t;
}
t = get_time(meta, "x-amz-meta-goog-reserved-file-mtime");
if(0 < t.tv_sec){
return t;
}
if(overcheck){
return {get_lastmodified(meta), 0};
}
return {-1, 0};
}
struct timespec get_ctime(const headers_t& meta, bool overcheck)
{
struct timespec t = get_time(meta, "x-amz-meta-ctime");
if(0 < t.tv_sec){
return t;
}
if(overcheck){
return {get_lastmodified(meta), 0};
}
return {-1, 0};
}
struct timespec get_atime(const headers_t& meta, bool overcheck)
{
struct timespec t = get_time(meta, "x-amz-meta-atime");
if(0 < t.tv_sec){
return t;
}
if(overcheck){
return {get_lastmodified(meta), 0};
}
return {-1, 0};
}
off_t get_size(const char *s)
{
return cvt_strtoofft(s, /*base=*/ 10);
}
off_t get_size(const headers_t& meta)
{
headers_t::const_iterator iter = meta.find("Content-Length");
if(meta.end() == iter){
return 0;
}
return get_size((*iter).second.c_str());
}
mode_t get_mode(const char *s, int base)
{
return static_cast<mode_t>(cvt_strtoofft(s, base));
}
mode_t get_mode(const headers_t& meta, const char* path, bool checkdir, bool forcedir)
{
mode_t mode = 0;
bool isS3sync = false;
headers_t::const_iterator iter;
if(meta.end() != (iter = meta.find("x-amz-meta-mode"))){
mode = get_mode((*iter).second.c_str());
}else if(meta.end() != (iter = meta.find("x-amz-meta-permissions"))){ // for s3sync
mode = get_mode((*iter).second.c_str());
isS3sync = true;
}else if(meta.end() != (iter = meta.find("x-amz-meta-goog-reserved-posix-mode"))){ // for GCS
mode = get_mode((*iter).second.c_str(), 8);
}else{
// If another tool creates an object without permissions, default to owner
// read-write and group readable.
mode = path[strlen(path) - 1] == '/' ? 0750 : 0640;
}
// Checking the bitmask, if the last 3 bits are all zero then process as a regular
// file type (S_IFDIR or S_IFREG), otherwise return mode unmodified so that S_IFIFO,
// S_IFSOCK, S_IFCHR, S_IFLNK and S_IFBLK devices can be processed properly by fuse.
if(!(mode & S_IFMT)){
if(!isS3sync){
if(checkdir){
if(forcedir){
mode |= S_IFDIR;
}else{
if(meta.end() != (iter = meta.find("Content-Type"))){
std::string strConType = (*iter).second;
// Leave just the mime type, remove any optional parameters (eg charset)
std::string::size_type pos = strConType.find(';');
if(std::string::npos != pos){
strConType.erase(pos);
}
if(strConType == "application/x-directory" || strConType == "httpd/unix-directory"){
// Nextcloud uses this MIME type for directory objects when mounting bucket as external Storage
mode |= S_IFDIR;
}else if(path && 0 < strlen(path) && '/' == path[strlen(path) - 1]){
if(strConType == "binary/octet-stream" || strConType == "application/octet-stream"){
mode |= S_IFDIR;
}else{
if(complement_stat){
// If complement lack stat mode, when the object has '/' character at end of name
// and content type is text/plain and the object's size is 0 or 1, it should be
// directory.
off_t size = get_size(meta);
if(strConType == "text/plain" && (0 == size || 1 == size)){
mode |= S_IFDIR;
}else{
mode |= S_IFREG;
}
}else{
mode |= S_IFREG;
}
}
}else{
mode |= S_IFREG;
}
}else{
mode |= S_IFREG;
}
}
}
// If complement lack stat mode, when it's mode is not set any permission,
// the object is added minimal mode only for read permission.
if(complement_stat && 0 == (mode & (S_IRWXU | S_IRWXG | S_IRWXO))){
mode |= (S_IRUSR | (0 == (mode & S_IFDIR) ? 0 : S_IXUSR));
}
}else{
if(!checkdir){
// cut dir/reg flag.
mode &= ~S_IFDIR;
mode &= ~S_IFREG;
}
}
}
return mode;
}
uid_t get_uid(const char *s)
{
return static_cast<uid_t>(cvt_strtoofft(s, /*base=*/ 0));
}
uid_t get_uid(const headers_t& meta)
{
headers_t::const_iterator iter;
if(meta.end() != (iter = meta.find("x-amz-meta-uid"))){
return get_uid((*iter).second.c_str());
}else if(meta.end() != (iter = meta.find("x-amz-meta-owner"))){ // for s3sync
return get_uid((*iter).second.c_str());
}else if(meta.end() != (iter = meta.find("x-amz-meta-goog-reserved-posix-uid"))){ // for GCS
return get_uid((*iter).second.c_str());
}else{
return geteuid();
}
}
gid_t get_gid(const char *s)
{
return static_cast<gid_t>(cvt_strtoofft(s, /*base=*/ 0));
}
gid_t get_gid(const headers_t& meta)
{
headers_t::const_iterator iter;
if(meta.end() != (iter = meta.find("x-amz-meta-gid"))){
return get_gid((*iter).second.c_str());
}else if(meta.end() != (iter = meta.find("x-amz-meta-group"))){ // for s3sync
return get_gid((*iter).second.c_str());
}else if(meta.end() != (iter = meta.find("x-amz-meta-goog-reserved-posix-gid"))){ // for GCS
return get_gid((*iter).second.c_str());
}else{
return getegid();
}
}
blkcnt_t get_blocks(off_t size)
{
return size / 512 + 1;
}
time_t cvtIAMExpireStringToTime(const char* s)
{
struct tm tm;
if(!s){
return 0L;
}
memset(&tm, 0, sizeof(struct tm));
strptime(s, "%Y-%m-%dT%H:%M:%S", &tm);
return timegm(&tm); // GMT
}
time_t get_lastmodified(const char* s)
{
struct tm tm;
if(!s){
return -1;
}
memset(&tm, 0, sizeof(struct tm));
strptime(s, "%a, %d %b %Y %H:%M:%S %Z", &tm);
return timegm(&tm); // GMT
}
time_t get_lastmodified(const headers_t& meta)
{
headers_t::const_iterator iter = meta.find("Last-Modified");
if(meta.end() == iter){
return -1;
}
return get_lastmodified((*iter).second.c_str());
}
//
// Returns it whether it is an object with need checking in detail.
// If this function returns true, the object is possible to be directory
// and is needed checking detail(searching sub object).
//
bool is_need_check_obj_detail(const headers_t& meta)
{
headers_t::const_iterator iter;
// directory object is Content-Length as 0.
if(0 != get_size(meta)){
return false;
}
// if the object has x-amz-meta information, checking is no more.
if(meta.end() != meta.find("x-amz-meta-mode") ||
meta.end() != meta.find("x-amz-meta-mtime") ||
meta.end() != meta.find("x-amz-meta-ctime") ||
meta.end() != meta.find("x-amz-meta-atime") ||
meta.end() != meta.find("x-amz-meta-uid") ||
meta.end() != meta.find("x-amz-meta-gid") ||
meta.end() != meta.find("x-amz-meta-owner") ||
meta.end() != meta.find("x-amz-meta-group") ||
meta.end() != meta.find("x-amz-meta-permissions") )
{
return false;
}
// if there is not Content-Type, or Content-Type is "x-directory",
// checking is no more.
if(meta.end() == (iter = meta.find("Content-Type"))){
return false;
}
if("application/x-directory" == (*iter).second){
return false;
}
return true;
}
// [NOTE]
// If add_noexist is false and the key does not exist, it will not be added.
//
bool merge_headers(headers_t& base, const headers_t& additional, bool add_noexist)
{
bool added = false;
for(headers_t::const_iterator iter = additional.begin(); iter != additional.end(); ++iter){
if(add_noexist || base.find(iter->first) != base.end()){
base[iter->first] = iter->second;
added = true;
}
}
return added;
}
/*
* 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
*/

71
src/metaheader.h Normal file
View File

@ -0,0 +1,71 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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.
*/
#ifndef S3FS_METAHEADER_H_
#define S3FS_METAHEADER_H_
#include <string>
#include <map>
#include <list>
//-------------------------------------------------------------------
// headers_t
//-------------------------------------------------------------------
struct header_nocase_cmp : public std::binary_function<std::string, std::string, bool>
{
bool operator()(const std::string &strleft, const std::string &strright) const
{
return (strcasecmp(strleft.c_str(), strright.c_str()) < 0);
}
};
typedef std::map<std::string, std::string, header_nocase_cmp> headers_t;
//-------------------------------------------------------------------
// Functions
//-------------------------------------------------------------------
struct timespec get_mtime(const headers_t& meta, bool overcheck = true);
struct timespec get_ctime(const headers_t& meta, bool overcheck = true);
struct timespec get_atime(const headers_t& meta, bool overcheck = true);
off_t get_size(const char *s);
off_t get_size(const headers_t& meta);
mode_t get_mode(const char *s, int base = 0);
mode_t get_mode(const headers_t& meta, const char* path = NULL, bool checkdir = false, bool forcedir = false);
uid_t get_uid(const char *s);
uid_t get_uid(const headers_t& meta);
gid_t get_gid(const char *s);
gid_t get_gid(const headers_t& meta);
blkcnt_t get_blocks(off_t size);
time_t cvtIAMExpireStringToTime(const char* s);
time_t get_lastmodified(const char* s);
time_t get_lastmodified(const headers_t& meta);
bool is_need_check_obj_detail(const headers_t& meta);
bool merge_headers(headers_t& base, const headers_t& additional, bool add_noexist);
bool simple_parse_xml(const char* data, size_t len, const char* key, std::string& value);
#endif // S3FS_METAHEADER_H_
/*
* 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
*/

159
src/mpu_util.cpp Normal file
View File

@ -0,0 +1,159 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Takeshi Nakatani <ggtakec.com>
*
* 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 <cstdio>
#include <cstdlib>
#include "common.h"
#include "s3fs.h"
#include "mpu_util.h"
#include "curl.h"
#include "s3fs_xml.h"
#include "s3fs_auth.h"
#include "string_util.h"
//-------------------------------------------------------------------
// Global variables
//-------------------------------------------------------------------
utility_incomp_type utility_mode = NO_UTILITY_MODE;
//-------------------------------------------------------------------
// Functions
//-------------------------------------------------------------------
static void print_incomp_mpu_list(incomp_mpu_list_t& list)
{
printf("\n");
printf("Lists the parts that have been uploaded for a specific multipart upload.\n");
printf("\n");
if(!list.empty()){
printf("---------------------------------------------------------------\n");
int cnt = 0;
for(incomp_mpu_list_t::iterator iter = list.begin(); iter != list.end(); ++iter, ++cnt){
printf(" Path : %s\n", (*iter).key.c_str());
printf(" UploadId : %s\n", (*iter).id.c_str());
printf(" Date : %s\n", (*iter).date.c_str());
printf("\n");
}
printf("---------------------------------------------------------------\n");
}else{
printf("There is no list.\n");
}
}
static bool abort_incomp_mpu_list(incomp_mpu_list_t& list, time_t abort_time)
{
if(list.empty()){
return true;
}
time_t now_time = time(NULL);
// do removing.
S3fsCurl s3fscurl;
bool result = true;
for(incomp_mpu_list_t::iterator iter = list.begin(); iter != list.end(); ++iter){
const char* tpath = (*iter).key.c_str();
std::string upload_id = (*iter).id;
if(0 != abort_time){ // abort_time is 0, it means all.
time_t date = 0;
if(!get_unixtime_from_iso8601((*iter).date.c_str(), date)){
S3FS_PRN_DBG("date format is not ISO 8601 for %s multipart uploading object, skip this.", tpath);
continue;
}
if(now_time <= (date + abort_time)){
continue;
}
}
if(0 != s3fscurl.AbortMultipartUpload(tpath, upload_id)){
S3FS_PRN_EXIT("Failed to remove %s multipart uploading object.", tpath);
result = false;
}else{
printf("Succeed to remove %s multipart uploading object.\n", tpath);
}
// reset(initialize) curl object
s3fscurl.DestroyCurlHandle();
}
return result;
}
int s3fs_utility_processing(time_t abort_time)
{
if(NO_UTILITY_MODE == utility_mode){
return EXIT_FAILURE;
}
printf("\n*** s3fs run as utility mode.\n\n");
S3fsCurl s3fscurl;
std::string body;
int result = EXIT_SUCCESS;
if(0 != s3fscurl.MultipartListRequest(body)){
S3FS_PRN_EXIT("Could not get list multipart upload.\nThere is no incomplete multipart uploaded object in bucket.\n");
result = EXIT_FAILURE;
}else{
// parse result(incomplete multipart upload information)
S3FS_PRN_DBG("response body = {\n%s\n}", body.c_str());
xmlDocPtr doc;
if(NULL == (doc = xmlReadMemory(body.c_str(), static_cast<int>(body.size()), "", NULL, 0))){
S3FS_PRN_DBG("xmlReadMemory exited with error.");
result = EXIT_FAILURE;
}else{
// make incomplete uploads list
incomp_mpu_list_t list;
if(!get_incomp_mpu_list(doc, list)){
S3FS_PRN_DBG("get_incomp_mpu_list exited with error.");
result = EXIT_FAILURE;
}else{
if(INCOMP_TYPE_LIST == utility_mode){
// print list
print_incomp_mpu_list(list);
}else if(INCOMP_TYPE_ABORT == utility_mode){
// remove
if(!abort_incomp_mpu_list(list, abort_time)){
S3FS_PRN_DBG("an error occurred during removal process.");
result = EXIT_FAILURE;
}
}
}
S3FS_XMLFREEDOC(doc);
}
}
// ssl
s3fs_destroy_global_ssl();
return result;
}
/*
* 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
*/

64
src/mpu_util.h Normal file
View File

@ -0,0 +1,64 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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.
*/
#ifndef S3FS_MPU_UTIL_H_
#define S3FS_MPU_UTIL_H_
#include <string>
#include <list>
//-------------------------------------------------------------------
// Structure / Typedef
//-------------------------------------------------------------------
typedef struct incomplete_multipart_upload_info
{
std::string key;
std::string id;
std::string date;
}INCOMP_MPU_INFO;
typedef std::list<INCOMP_MPU_INFO> incomp_mpu_list_t;
//-------------------------------------------------------------------
// enum for utility process mode
//-------------------------------------------------------------------
enum utility_incomp_type{
NO_UTILITY_MODE = 0, // not utility mode
INCOMP_TYPE_LIST, // list of incomplete mpu
INCOMP_TYPE_ABORT // delete incomplete mpu
};
extern utility_incomp_type utility_mode;
//-------------------------------------------------------------------
// Functions
//-------------------------------------------------------------------
int s3fs_utility_processing(time_t abort_time);
#endif // S3FS_MPU_UTIL_H_
/*
* 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
*/

139
src/mvnode.cpp Normal file
View File

@ -0,0 +1,139 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Takeshi Nakatani <ggtakec.com>
*
* 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 <cstdio>
#include <cstdlib>
#include "common.h"
#include "s3fs.h"
#include "mvnode.h"
//-------------------------------------------------------------------
// Utility functions for moving objects
//-------------------------------------------------------------------
MVNODE *create_mvnode(const char *old_path, const char *new_path, bool is_dir, bool normdir)
{
MVNODE *p;
char *p_old_path;
char *p_new_path;
if(NULL == (p_old_path = strdup(old_path))){
printf("create_mvnode: could not allocation memory for p_old_path\n");
S3FS_FUSE_EXIT();
return NULL;
}
if(NULL == (p_new_path = strdup(new_path))){
free(p_old_path);
printf("create_mvnode: could not allocation memory for p_new_path\n");
S3FS_FUSE_EXIT();
return NULL;
}
p = new MVNODE();
p->old_path = p_old_path;
p->new_path = p_new_path;
p->is_dir = is_dir;
p->is_normdir = normdir;
p->prev = NULL;
p->next = NULL;
return p;
}
//
// Add sorted MVNODE data(Ascending order)
//
MVNODE *add_mvnode(MVNODE** head, MVNODE** tail, const char *old_path, const char *new_path, bool is_dir, bool normdir)
{
if(!head || !tail){
return NULL;
}
MVNODE* cur;
MVNODE* mvnew;
for(cur = *head; cur; cur = cur->next){
if(cur->is_dir == is_dir){
int nResult = strcmp(cur->old_path, old_path);
if(0 == nResult){
// Found same old_path.
return cur;
}else if(0 > nResult){
// next check.
// ex: cur("abc"), mvnew("abcd")
// ex: cur("abc"), mvnew("abd")
continue;
}else{
// Add into before cur-pos.
// ex: cur("abc"), mvnew("ab")
// ex: cur("abc"), mvnew("abb")
if(NULL == (mvnew = create_mvnode(old_path, new_path, is_dir, normdir))){
return NULL;
}
if(cur->prev){
(cur->prev)->next = mvnew;
}else{
*head = mvnew;
}
mvnew->prev = cur->prev;
mvnew->next = cur;
cur->prev = mvnew;
return mvnew;
}
}
}
// Add into tail.
if(NULL == (mvnew = create_mvnode(old_path, new_path, is_dir, normdir))){
return NULL;
}
mvnew->prev = (*tail);
if(*tail){
(*tail)->next = mvnew;
}
(*tail) = mvnew;
if(!(*head)){
(*head) = mvnew;
}
return mvnew;
}
void free_mvnodes(MVNODE *head)
{
MVNODE *my_head;
MVNODE *next;
for(my_head = head, next = NULL; my_head; my_head = next){
next = my_head->next;
free(my_head->old_path);
free(my_head->new_path);
delete my_head;
}
}
/*
* 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
*/

53
src/mvnode.h Normal file
View File

@ -0,0 +1,53 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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.
*/
#ifndef S3FS_MVNODE_H_
#define S3FS_MVNODE_H_
//-------------------------------------------------------------------
// Structure
//-------------------------------------------------------------------
typedef struct mvnode
{
char* old_path;
char* new_path;
bool is_dir;
bool is_normdir;
struct mvnode* prev;
struct mvnode* next;
} MVNODE;
//-------------------------------------------------------------------
// Utility functions for moving objects
//-------------------------------------------------------------------
MVNODE *create_mvnode(const char *old_path, const char *new_path, bool is_dir, bool normdir = false);
MVNODE *add_mvnode(MVNODE** head, MVNODE** tail, const char *old_path, const char *new_path, bool is_dir, bool normdir = false);
void free_mvnodes(MVNODE *head);
#endif // S3FS_MVNODE_H_
/*
* 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
*/

View File

@ -1,7 +1,7 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright 2007-2008 Randy Rizun <rrizun@gmail.com>
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -35,162 +35,224 @@
#include <map>
#include "common.h"
#include "s3fs.h"
#include "s3fs_auth.h"
using namespace std;
//-------------------------------------------------------------------
// Utility Function for version
//-------------------------------------------------------------------
const char* s3fs_crypt_lib_name(void)
const char* s3fs_crypt_lib_name()
{
static const char version[] = "NSS";
static const char version[] = "NSS";
return version;
return version;
}
//-------------------------------------------------------------------
// Utility Function for global init
//-------------------------------------------------------------------
bool s3fs_init_global_ssl(void)
bool s3fs_init_global_ssl()
{
NSS_Init(NULL);
NSS_NoDB_Init(NULL);
return true;
PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
if(SECSuccess != NSS_NoDB_Init(NULL)){
S3FS_PRN_ERR("Failed NSS_NoDB_Init call.");
return false;
}
return true;
}
bool s3fs_destroy_global_ssl(void)
bool s3fs_destroy_global_ssl()
{
NSS_Shutdown();
PL_ArenaFinish();
PR_Cleanup();
return true;
NSS_Shutdown();
PL_ArenaFinish();
PR_Cleanup();
return true;
}
//-------------------------------------------------------------------
// Utility Function for crypt lock
//-------------------------------------------------------------------
bool s3fs_init_crypt_mutex(void)
bool s3fs_init_crypt_mutex()
{
return true;
return true;
}
bool s3fs_destroy_crypt_mutex(void)
bool s3fs_destroy_crypt_mutex()
{
return true;
return true;
}
//-------------------------------------------------------------------
// Utility Function for HMAC
//-------------------------------------------------------------------
bool s3fs_HMAC(const void* key, size_t keylen, const unsigned char* data, size_t datalen, unsigned char** digest, unsigned int* digestlen)
static bool s3fs_HMAC_RAW(const void* key, size_t keylen, const unsigned char* data, size_t datalen, unsigned char** digest, unsigned int* digestlen, bool is_sha256)
{
if(!key || 0 >= keylen || !data || 0 >= datalen || !digest || !digestlen){
return false;
}
if(!key || !data || !digest || !digestlen){
return false;
}
PK11SlotInfo* Slot;
PK11SymKey* pKey;
PK11Context* Context;
SECStatus SecStatus;
unsigned char tmpdigest[64];
SECItem KeySecItem = {siBuffer, reinterpret_cast<unsigned char*>(const_cast<void*>(key)), keylen};
SECItem NullSecItem = {siBuffer, NULL, 0};
PK11SlotInfo* Slot;
PK11SymKey* pKey;
PK11Context* Context;
unsigned char tmpdigest[64];
SECItem KeySecItem = {siBuffer, reinterpret_cast<unsigned char*>(const_cast<void*>(key)), static_cast<unsigned int>(keylen)};
SECItem NullSecItem = {siBuffer, NULL, 0};
if(NULL == (Slot = PK11_GetInternalKeySlot())){
return false;
}
if(NULL == (pKey = PK11_ImportSymKey(Slot, CKM_SHA_1_HMAC, PK11_OriginUnwrap, CKA_SIGN, &KeySecItem, NULL))){
PK11_FreeSlot(Slot);
return false;
}
if(NULL == (Context = PK11_CreateContextBySymKey(CKM_SHA_1_HMAC, CKA_SIGN, pKey, &NullSecItem))){
PK11_FreeSymKey(pKey);
PK11_FreeSlot(Slot);
return false;
}
if(NULL == (Slot = PK11_GetInternalKeySlot())){
return false;
}
if(NULL == (pKey = PK11_ImportSymKey(Slot, (is_sha256 ? CKM_SHA256_HMAC : CKM_SHA_1_HMAC), PK11_OriginUnwrap, CKA_SIGN, &KeySecItem, NULL))){
PK11_FreeSlot(Slot);
return false;
}
if(NULL == (Context = PK11_CreateContextBySymKey((is_sha256 ? CKM_SHA256_HMAC : CKM_SHA_1_HMAC), CKA_SIGN, pKey, &NullSecItem))){
PK11_FreeSymKey(pKey);
PK11_FreeSlot(Slot);
return false;
}
*digestlen = 0;
if(SECSuccess != (SecStatus = PK11_DigestBegin(Context)) ||
SECSuccess != (SecStatus = PK11_DigestOp(Context, data, datalen)) ||
SECSuccess != (SecStatus = PK11_DigestFinal(Context, tmpdigest, digestlen, sizeof(tmpdigest))) )
{
*digestlen = 0;
if(SECSuccess != PK11_DigestBegin(Context) ||
SECSuccess != PK11_DigestOp(Context, data, datalen) ||
SECSuccess != PK11_DigestFinal(Context, tmpdigest, digestlen, sizeof(tmpdigest)) )
{
PK11_DestroyContext(Context, PR_TRUE);
PK11_FreeSymKey(pKey);
PK11_FreeSlot(Slot);
return false;
}
PK11_DestroyContext(Context, PR_TRUE);
PK11_FreeSymKey(pKey);
PK11_FreeSlot(Slot);
return false;
}
PK11_DestroyContext(Context, PR_TRUE);
PK11_FreeSymKey(pKey);
PK11_FreeSlot(Slot);
if(NULL == (*digest = (unsigned char*)malloc(*digestlen))){
return false;
}
memcpy(*digest, tmpdigest, *digestlen);
*digest = new unsigned char[*digestlen];
memcpy(*digest, tmpdigest, *digestlen);
return true;
return true;
}
bool s3fs_HMAC(const void* key, size_t keylen, const unsigned char* data, size_t datalen, unsigned char** digest, unsigned int* digestlen)
{
return s3fs_HMAC_RAW(key, keylen, data, datalen, digest, digestlen, false);
}
bool s3fs_HMAC256(const void* key, size_t keylen, const unsigned char* data, size_t datalen, unsigned char** digest, unsigned int* digestlen)
{
return s3fs_HMAC_RAW(key, keylen, data, datalen, digest, digestlen, true);
}
//-------------------------------------------------------------------
// Utility Function for MD5
//-------------------------------------------------------------------
size_t get_md5_digest_length(void)
size_t get_md5_digest_length()
{
return MD5_LENGTH;
return MD5_LENGTH;
}
unsigned char* s3fs_md5hexsum(int fd, off_t start, ssize_t size)
unsigned char* s3fs_md5_fd(int fd, off_t start, off_t size)
{
PK11Context* md5ctx;
unsigned char buf[512];
ssize_t bytes;
unsigned char* result;
unsigned int md5outlen;
PK11Context* md5ctx;
off_t bytes;
unsigned char* result;
unsigned int md5outlen;
if(-1 == size){
struct stat st;
if(-1 == fstat(fd, &st)){
return NULL;
if(-1 == size){
struct stat st;
if(-1 == fstat(fd, &st)){
return NULL;
}
size = st.st_size;
}
size = static_cast<ssize_t>(st.st_size);
}
// seek to top of file.
if(-1 == lseek(fd, start, SEEK_SET)){
return NULL;
}
md5ctx = PK11_CreateDigestContext(SEC_OID_MD5);
memset(buf, 0, 512);
md5ctx = PK11_CreateDigestContext(SEC_OID_MD5);
for(ssize_t total = 0; total < size; total += bytes){
bytes = 512 < (size - total) ? 512 : (size - total);
bytes = read(fd, buf, bytes);
if(0 == bytes){
// end of file
break;
}else if(-1 == bytes){
// error
DPRNNN("file read error(%d)", errno);
return NULL;
for(off_t total = 0; total < size; total += bytes){
off_t len = 512;
unsigned char buf[len];
bytes = len < (size - total) ? len : (size - total);
bytes = pread(fd, buf, bytes, start + total);
if(0 == bytes){
// end of file
break;
}else if(-1 == bytes){
// error
S3FS_PRN_ERR("file read error(%d)", errno);
PK11_DestroyContext(md5ctx, PR_TRUE);
return NULL;
}
PK11_DigestOp(md5ctx, buf, bytes);
}
PK11_DigestOp(md5ctx, buf, bytes);
memset(buf, 0, 512);
}
if(NULL == (result = (unsigned char*)malloc(get_md5_digest_length()))){
result = new unsigned char[get_md5_digest_length()];
PK11_DigestFinal(md5ctx, result, &md5outlen, get_md5_digest_length());
PK11_DestroyContext(md5ctx, PR_TRUE);
return NULL;
}
PK11_DigestFinal(md5ctx, result, &md5outlen, get_md5_digest_length());
PK11_DestroyContext(md5ctx, PR_TRUE);
if(-1 == lseek(fd, start, SEEK_SET)){
free(result);
return NULL;
}
return result;
}
return result;
//-------------------------------------------------------------------
// Utility Function for SHA256
//-------------------------------------------------------------------
size_t get_sha256_digest_length()
{
return SHA256_LENGTH;
}
bool s3fs_sha256(const unsigned char* data, size_t datalen, unsigned char** digest, unsigned int* digestlen)
{
(*digestlen) = static_cast<unsigned int>(get_sha256_digest_length());
*digest = new unsigned char[*digestlen];
PK11Context* sha256ctx;
unsigned int sha256outlen;
sha256ctx = PK11_CreateDigestContext(SEC_OID_SHA256);
PK11_DigestOp(sha256ctx, data, datalen);
PK11_DigestFinal(sha256ctx, *digest, &sha256outlen, *digestlen);
PK11_DestroyContext(sha256ctx, PR_TRUE);
*digestlen = sha256outlen;
return true;
}
unsigned char* s3fs_sha256_fd(int fd, off_t start, off_t size)
{
PK11Context* sha256ctx;
off_t bytes;
unsigned char* result;
unsigned int sha256outlen;
if(-1 == size){
struct stat st;
if(-1 == fstat(fd, &st)){
return NULL;
}
size = st.st_size;
}
sha256ctx = PK11_CreateDigestContext(SEC_OID_SHA256);
for(off_t total = 0; total < size; total += bytes){
off_t len = 512;
unsigned char buf[len];
bytes = len < (size - total) ? len : (size - total);
bytes = pread(fd, buf, bytes, start + total);
if(0 == bytes){
// end of file
break;
}else if(-1 == bytes){
// error
S3FS_PRN_ERR("file read error(%d)", errno);
PK11_DestroyContext(sha256ctx, PR_TRUE);
return NULL;
}
PK11_DigestOp(sha256ctx, buf, bytes);
}
result = new unsigned char[get_sha256_digest_length()];
PK11_DigestFinal(sha256ctx, result, &sha256outlen, get_sha256_digest_length());
PK11_DestroyContext(sha256ctx, PR_TRUE);
return result;
}
/*
@ -198,6 +260,6 @@ unsigned char* s3fs_md5hexsum(int fd, off_t start, ssize_t size)
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
* vim600: expandtab sw=4 ts=4 fdm=marker
* vim<600: expandtab sw=4 ts=4
*/

View File

@ -1,7 +1,7 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright 2007-2008 Randy Rizun <rrizun@gmail.com>
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -18,56 +18,56 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <cstdio>
#include <cstdlib>
#include <cerrno>
#include <pthread.h>
#include <unistd.h>
#include <syslog.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <cstring>
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <string>
#include <map>
#include "common.h"
#include "s3fs.h"
#include "s3fs_auth.h"
using namespace std;
//-------------------------------------------------------------------
// Utility Function for version
//-------------------------------------------------------------------
const char* s3fs_crypt_lib_name(void)
const char* s3fs_crypt_lib_name()
{
static const char version[] = "OpenSSL";
static const char version[] = "OpenSSL";
return version;
return version;
}
//-------------------------------------------------------------------
// Utility Function for global init
//-------------------------------------------------------------------
bool s3fs_init_global_ssl(void)
bool s3fs_init_global_ssl()
{
ERR_load_crypto_strings();
ERR_load_BIO_strings();
OpenSSL_add_all_algorithms();
return true;
ERR_load_crypto_strings();
ERR_load_BIO_strings();
OpenSSL_add_all_algorithms();
return true;
}
bool s3fs_destroy_global_ssl(void)
bool s3fs_destroy_global_ssl()
{
EVP_cleanup();
ERR_free_strings();
return true;
EVP_cleanup();
ERR_free_strings();
return true;
}
//-------------------------------------------------------------------
@ -76,181 +76,287 @@ bool s3fs_destroy_global_ssl(void)
// internal use struct for openssl
struct CRYPTO_dynlock_value
{
pthread_mutex_t dyn_mutex;
pthread_mutex_t dyn_mutex;
};
static pthread_mutex_t* s3fs_crypt_mutex = NULL;
static void s3fs_crypt_mutex_lock(int mode, int pos, const char* file, int line) __attribute__ ((unused));
static void s3fs_crypt_mutex_lock(int mode, int pos, const char* file, int line)
{
if(s3fs_crypt_mutex){
if(mode & CRYPTO_LOCK){
pthread_mutex_lock(&s3fs_crypt_mutex[pos]);
}else{
pthread_mutex_unlock(&s3fs_crypt_mutex[pos]);
if(s3fs_crypt_mutex){
int result;
if(mode & CRYPTO_LOCK){
if(0 != (result = pthread_mutex_lock(&s3fs_crypt_mutex[pos]))){
S3FS_PRN_CRIT("pthread_mutex_lock returned: %d", result);
abort();
}
}else{
if(0 != (result = pthread_mutex_unlock(&s3fs_crypt_mutex[pos]))){
S3FS_PRN_CRIT("pthread_mutex_unlock returned: %d", result);
abort();
}
}
}
}
}
static unsigned long s3fs_crypt_get_threadid(void)
static unsigned long s3fs_crypt_get_threadid() __attribute__ ((unused));
static unsigned long s3fs_crypt_get_threadid()
{
return static_cast<unsigned long>(pthread_self());
// For FreeBSD etc, some system's pthread_t is structure pointer.
// Then we use cast like C style(not C++) instead of ifdef.
return (unsigned long)(pthread_self());
}
static struct CRYPTO_dynlock_value* s3fs_dyn_crypt_mutex(const char* file, int line) __attribute__ ((unused));
static struct CRYPTO_dynlock_value* s3fs_dyn_crypt_mutex(const char* file, int line)
{
struct CRYPTO_dynlock_value* dyndata;
if(NULL == (dyndata = static_cast<struct CRYPTO_dynlock_value*>(malloc(sizeof(struct CRYPTO_dynlock_value))))){
DPRNCRIT("Could not allocate memory for CRYPTO_dynlock_value");
return NULL;
}
pthread_mutex_init(&(dyndata->dyn_mutex), NULL);
return dyndata;
struct CRYPTO_dynlock_value* dyndata = new CRYPTO_dynlock_value();
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
#if S3FS_PTHREAD_ERRORCHECK
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
#endif
int result;
if(0 != (result = pthread_mutex_init(&(dyndata->dyn_mutex), &attr))){
S3FS_PRN_CRIT("pthread_mutex_init returned: %d", result);
return NULL;
}
return dyndata;
}
static void s3fs_dyn_crypt_mutex_lock(int mode, struct CRYPTO_dynlock_value* dyndata, const char* file, int line) __attribute__ ((unused));
static void s3fs_dyn_crypt_mutex_lock(int mode, struct CRYPTO_dynlock_value* dyndata, const char* file, int line)
{
if(dyndata){
if(mode & CRYPTO_LOCK){
pthread_mutex_lock(&(dyndata->dyn_mutex));
}else{
pthread_mutex_unlock(&(dyndata->dyn_mutex));
if(dyndata){
int result;
if(mode & CRYPTO_LOCK){
if(0 != (result = pthread_mutex_lock(&(dyndata->dyn_mutex)))){
S3FS_PRN_CRIT("pthread_mutex_lock returned: %d", result);
abort();
}
}else{
if(0 != (result = pthread_mutex_unlock(&(dyndata->dyn_mutex)))){
S3FS_PRN_CRIT("pthread_mutex_unlock returned: %d", result);
abort();
}
}
}
}
}
static void s3fs_destroy_dyn_crypt_mutex(struct CRYPTO_dynlock_value* dyndata, const char* file, int line) __attribute__ ((unused));
static void s3fs_destroy_dyn_crypt_mutex(struct CRYPTO_dynlock_value* dyndata, const char* file, int line)
{
if(dyndata){
pthread_mutex_destroy(&(dyndata->dyn_mutex));
free(dyndata);
}
}
bool s3fs_init_crypt_mutex(void)
{
if(s3fs_crypt_mutex){
FPRNNN("s3fs_crypt_mutex is not NULL, destory it.");
if(!s3fs_destroy_crypt_mutex()){
DPRN("Failed to s3fs_crypt_mutex");
return false;
if(dyndata){
int result = pthread_mutex_destroy(&(dyndata->dyn_mutex));
if(result != 0){
S3FS_PRN_CRIT("failed to destroy dyn_mutex");
abort();
}
delete dyndata;
}
}
if(NULL == (s3fs_crypt_mutex = static_cast<pthread_mutex_t*>(malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t))))){
DPRNCRIT("Could not allocate memory for s3fs_crypt_mutex");
return false;
}
for(int cnt = 0; cnt < CRYPTO_num_locks(); cnt++){
pthread_mutex_init(&s3fs_crypt_mutex[cnt], NULL);
}
// static lock
CRYPTO_set_locking_callback(s3fs_crypt_mutex_lock);
CRYPTO_set_id_callback(s3fs_crypt_get_threadid);
// dynamic lock
CRYPTO_set_dynlock_create_callback(s3fs_dyn_crypt_mutex);
CRYPTO_set_dynlock_lock_callback(s3fs_dyn_crypt_mutex_lock);
CRYPTO_set_dynlock_destroy_callback(s3fs_destroy_dyn_crypt_mutex);
return true;
}
bool s3fs_destroy_crypt_mutex(void)
bool s3fs_init_crypt_mutex()
{
if(!s3fs_crypt_mutex){
if(s3fs_crypt_mutex){
S3FS_PRN_DBG("s3fs_crypt_mutex is not NULL, destroy it.");
if(!s3fs_destroy_crypt_mutex()){
S3FS_PRN_ERR("Failed to s3fs_crypt_mutex");
return false;
}
}
s3fs_crypt_mutex = new pthread_mutex_t[CRYPTO_num_locks()];
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
#if S3FS_PTHREAD_ERRORCHECK
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
#endif
for(int cnt = 0; cnt < CRYPTO_num_locks(); cnt++){
int result = pthread_mutex_init(&s3fs_crypt_mutex[cnt], &attr);
if(result != 0){
S3FS_PRN_CRIT("pthread_mutex_init returned: %d", result);
return false;
}
}
// static lock
CRYPTO_set_locking_callback(s3fs_crypt_mutex_lock);
CRYPTO_set_id_callback(s3fs_crypt_get_threadid);
// dynamic lock
CRYPTO_set_dynlock_create_callback(s3fs_dyn_crypt_mutex);
CRYPTO_set_dynlock_lock_callback(s3fs_dyn_crypt_mutex_lock);
CRYPTO_set_dynlock_destroy_callback(s3fs_destroy_dyn_crypt_mutex);
return true;
}
}
CRYPTO_set_dynlock_destroy_callback(NULL);
CRYPTO_set_dynlock_lock_callback(NULL);
CRYPTO_set_dynlock_create_callback(NULL);
CRYPTO_set_id_callback(NULL);
CRYPTO_set_locking_callback(NULL);
bool s3fs_destroy_crypt_mutex()
{
if(!s3fs_crypt_mutex){
return true;
}
for(int cnt = 0; cnt < CRYPTO_num_locks(); cnt++){
pthread_mutex_destroy(&s3fs_crypt_mutex[cnt]);
}
CRYPTO_cleanup_all_ex_data();
free(s3fs_crypt_mutex);
s3fs_crypt_mutex = NULL;
CRYPTO_set_dynlock_destroy_callback(NULL);
CRYPTO_set_dynlock_lock_callback(NULL);
CRYPTO_set_dynlock_create_callback(NULL);
CRYPTO_set_id_callback(NULL);
CRYPTO_set_locking_callback(NULL);
return true;
for(int cnt = 0; cnt < CRYPTO_num_locks(); cnt++){
int result = pthread_mutex_destroy(&s3fs_crypt_mutex[cnt]);
if(result != 0){
S3FS_PRN_CRIT("failed to destroy s3fs_crypt_mutex[%d]", cnt);
abort();
}
}
CRYPTO_cleanup_all_ex_data();
delete[] s3fs_crypt_mutex;
s3fs_crypt_mutex = NULL;
return true;
}
//-------------------------------------------------------------------
// Utility Function for HMAC
//-------------------------------------------------------------------
static bool s3fs_HMAC_RAW(const void* key, size_t keylen, const unsigned char* data, size_t datalen, unsigned char** digest, unsigned int* digestlen, bool is_sha256)
{
if(!key || !data || !digest || !digestlen){
return false;
}
(*digestlen) = EVP_MAX_MD_SIZE * sizeof(unsigned char);
*digest = new unsigned char[*digestlen];
if(is_sha256){
HMAC(EVP_sha256(), key, static_cast<int>(keylen), data, datalen, *digest, digestlen);
}else{
HMAC(EVP_sha1(), key, static_cast<int>(keylen), data, datalen, *digest, digestlen);
}
return true;
}
bool s3fs_HMAC(const void* key, size_t keylen, const unsigned char* data, size_t datalen, unsigned char** digest, unsigned int* digestlen)
{
if(!key || 0 >= keylen || !data || 0 >= datalen || !digest || !digestlen){
return false;
}
(*digestlen) = EVP_MAX_MD_SIZE * sizeof(unsigned char);
if(NULL == ((*digest) = (unsigned char*)malloc(*digestlen))){
return false;
}
HMAC(EVP_sha1(), key, keylen, data, datalen, *digest, digestlen);
return s3fs_HMAC_RAW(key, keylen, data, datalen, digest, digestlen, false);
}
return true;
bool s3fs_HMAC256(const void* key, size_t keylen, const unsigned char* data, size_t datalen, unsigned char** digest, unsigned int* digestlen)
{
return s3fs_HMAC_RAW(key, keylen, data, datalen, digest, digestlen, true);
}
//-------------------------------------------------------------------
// Utility Function for MD5
//-------------------------------------------------------------------
size_t get_md5_digest_length(void)
size_t get_md5_digest_length()
{
return MD5_DIGEST_LENGTH;
return MD5_DIGEST_LENGTH;
}
unsigned char* s3fs_md5hexsum(int fd, off_t start, ssize_t size)
unsigned char* s3fs_md5_fd(int fd, off_t start, off_t size)
{
MD5_CTX md5ctx;
char buf[512];
ssize_t bytes;
unsigned char* result;
MD5_CTX md5ctx;
off_t bytes;
unsigned char* result;
if(-1 == size){
struct stat st;
if(-1 == fstat(fd, &st)){
return NULL;
if(-1 == size){
struct stat st;
if(-1 == fstat(fd, &st)){
return NULL;
}
size = st.st_size;
}
size = static_cast<ssize_t>(st.st_size);
}
// seek to top of file.
if(-1 == lseek(fd, start, SEEK_SET)){
return NULL;
}
MD5_Init(&md5ctx);
memset(buf, 0, 512);
MD5_Init(&md5ctx);
for(ssize_t total = 0; total < size; total += bytes){
bytes = 512 < (size - total) ? 512 : (size - total);
bytes = read(fd, buf, bytes);
if(0 == bytes){
// end of file
break;
}else if(-1 == bytes){
// error
DPRNNN("file read error(%d)", errno);
return NULL;
for(off_t total = 0; total < size; total += bytes){
const off_t len = 512;
char buf[len];
bytes = len < (size - total) ? len : (size - total);
bytes = pread(fd, buf, bytes, start + total);
if(0 == bytes){
// end of file
break;
}else if(-1 == bytes){
// error
S3FS_PRN_ERR("file read error(%d)", errno);
return NULL;
}
MD5_Update(&md5ctx, buf, bytes);
}
MD5_Update(&md5ctx, buf, bytes);
memset(buf, 0, 512);
}
if(NULL == (result = (unsigned char*)malloc(get_md5_digest_length()))){
return NULL;
}
MD5_Final(result, &md5ctx);
result = new unsigned char[get_md5_digest_length()];
MD5_Final(result, &md5ctx);
if(-1 == lseek(fd, start, SEEK_SET)){
free(result);
return NULL;
}
return result;
}
return result;
//-------------------------------------------------------------------
// Utility Function for SHA256
//-------------------------------------------------------------------
size_t get_sha256_digest_length()
{
return SHA256_DIGEST_LENGTH;
}
bool s3fs_sha256(const unsigned char* data, size_t datalen, unsigned char** digest, unsigned int* digestlen)
{
(*digestlen) = EVP_MAX_MD_SIZE * sizeof(unsigned char);
*digest = new unsigned char[*digestlen];
const EVP_MD* md = EVP_get_digestbyname("sha256");
EVP_MD_CTX* mdctx = EVP_MD_CTX_create();
EVP_DigestInit_ex(mdctx, md, NULL);
EVP_DigestUpdate(mdctx, data, datalen);
EVP_DigestFinal_ex(mdctx, *digest, digestlen);
EVP_MD_CTX_destroy(mdctx);
return true;
}
unsigned char* s3fs_sha256_fd(int fd, off_t start, off_t size)
{
const EVP_MD* md = EVP_get_digestbyname("sha256");
EVP_MD_CTX* sha256ctx;
off_t bytes;
unsigned char* result;
if(-1 == fd){
return NULL;
}
if(-1 == size){
struct stat st;
if(-1 == fstat(fd, &st)){
S3FS_PRN_ERR("fstat error(%d)", errno);
return NULL;
}
size = st.st_size;
}
sha256ctx = EVP_MD_CTX_create();
EVP_DigestInit_ex(sha256ctx, md, NULL);
for(off_t total = 0; total < size; total += bytes){
const off_t len = 512;
char buf[len];
bytes = len < (size - total) ? len : (size - total);
bytes = pread(fd, buf, bytes, start + total);
if(0 == bytes){
// end of file
break;
}else if(-1 == bytes){
// error
S3FS_PRN_ERR("file read error(%d)", errno);
EVP_MD_CTX_destroy(sha256ctx);
return NULL;
}
EVP_DigestUpdate(sha256ctx, buf, bytes);
}
result = new unsigned char[get_sha256_digest_length()];
EVP_DigestFinal_ex(sha256ctx, result, NULL);
EVP_MD_CTX_destroy(sha256ctx);
return result;
}
/*
@ -258,6 +364,6 @@ unsigned char* s3fs_md5hexsum(int fd, off_t start, ssize_t size)
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
* vim600: expandtab sw=4 ts=4 fdm=marker
* vim<600: expandtab sw=4 ts=4
*/

89
src/psemaphore.h Normal file
View File

@ -0,0 +1,89 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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.
*/
#ifndef S3FS_SEMAPHORE_H_
#define S3FS_SEMAPHORE_H_
//-------------------------------------------------------------------
// Class Semaphore
//-------------------------------------------------------------------
// portability wrapper for sem_t since macOS does not implement it
#ifdef __APPLE__
#include <dispatch/dispatch.h>
class Semaphore
{
public:
explicit Semaphore(int value) : value(value), sem(dispatch_semaphore_create(value)) {}
~Semaphore()
{
// macOS cannot destroy a semaphore with posts less than the initializer
for(int i = 0; i < get_value(); ++i){
post();
}
dispatch_release(sem);
}
void wait() { dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); }
void post() { dispatch_semaphore_signal(sem); }
int get_value() const { return value; }
private:
const int value;
dispatch_semaphore_t sem;
};
#else
#include <errno.h>
#include <semaphore.h>
class Semaphore
{
public:
explicit Semaphore(int value) : value(value) { sem_init(&mutex, 0, value); }
~Semaphore() { sem_destroy(&mutex); }
void wait()
{
int r;
do {
r = sem_wait(&mutex);
} while (r == -1 && errno == EINTR);
}
void post() { sem_post(&mutex); }
int get_value() const { return value; }
private:
const int value;
sem_t mutex;
};
#endif
#endif // S3FS_SEMAPHORE_H_
/*
* 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
*/

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright 2007-2008 Randy Rizun <rrizun@gmail.com>
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,82 +17,76 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef S3FS_S3_H_
#define S3FS_S3_H_
#ifndef S3FS_S3FS_H_
#define S3FS_S3FS_H_
#define FUSE_USE_VERSION 26
#define FIVE_GB 5368709120LL
#include <fuse.h>
#define S3FS_FUSE_EXIT() { \
struct fuse_context* pcxt = fuse_get_context(); \
if(pcxt){ \
fuse_exit(pcxt->fuse); \
} \
}
#define S3FS_FUSE_EXIT() \
do{ \
struct fuse_context* pcxt = fuse_get_context(); \
if(pcxt){ \
fuse_exit(pcxt->fuse); \
} \
}while(0)
// [NOTE]
// s3fs use many small allocated chunk in heap area for stats
// cache and parsing xml, etc. The OS may decide that giving
// this little memory back to the kernel will cause too much
// overhead and delay the operation.
// Address of gratitude, this workaround quotes a document of
// libxml2.( http://xmlsoft.org/xmlmem.html )
//
// s3fs use many small allocated chunk in heap area for
// stats cache and parsing xml, etc. The OS may decide
// that giving this little memory back to the kernel
// will cause too much overhead and delay the operation.
// So s3fs calls malloc_trim function to really get the
// memory back. Following macros is prepared for that
// your system does not have it.
//
// Address of gratitude, this workaround quotes a document
// of libxml2.
// http://xmlsoft.org/xmlmem.html
// When valgrind is used to test memory leak of s3fs, a large
// amount of chunk may be reported. You can check the memory
// release accurately by defining the S3FS_MALLOC_TRIM flag
// and building it. Also, when executing s3fs, you can define
// the MMAP_THRESHOLD environment variable and check more
// accurate memory leak.( see, man 3 free )
//
#ifdef S3FS_MALLOC_TRIM
#ifdef HAVE_MALLOC_TRIM
#include <malloc.h>
#define S3FS_MALLOCTRIM(pad) malloc_trim(pad)
#else // HAVE_MALLOC_TRIM
#define S3FS_MALLOCTRIM(pad)
#endif // HAVE_MALLOC_TRIM
#else // S3FS_MALLOC_TRIM
#define S3FS_MALLOCTRIM(pad)
#endif // S3FS_MALLOC_TRIM
#define DISPWARN_MALLOCTRIM(str)
#define S3FS_MALLOCTRIM(pad) malloc_trim(pad)
#define S3FS_XMLFREEDOC(doc) \
{ \
do{ \
xmlFreeDoc(doc); \
S3FS_MALLOCTRIM(0); \
}
}while(0)
#define S3FS_XMLFREE(ptr) \
{ \
do{ \
xmlFree(ptr); \
S3FS_MALLOCTRIM(0); \
}
}while(0)
#define S3FS_XMLXPATHFREECONTEXT(ctx) \
{ \
do{ \
xmlXPathFreeContext(ctx); \
S3FS_MALLOCTRIM(0); \
}
}while(0)
#define S3FS_XMLXPATHFREEOBJECT(obj) \
{ \
do{ \
xmlXPathFreeObject(obj); \
S3FS_MALLOCTRIM(0); \
}
}while(0)
#else // HAVE_MALLOC_TRIM
#define DISPWARN_MALLOCTRIM(str) \
fprintf(stderr, "Warning: %s without malloc_trim is possibility of the use memory increase.\n", program_name.c_str())
#define S3FS_MALLOCTRIM(pad)
#define S3FS_XMLFREEDOC(doc) xmlFreeDoc(doc)
#define S3FS_XMLFREE(ptr) xmlFree(ptr)
#define S3FS_XMLXPATHFREECONTEXT(ctx) xmlXPathFreeContext(ctx)
#define S3FS_XMLXPATHFREEOBJECT(obj) xmlXPathFreeObject(obj)
#endif // HAVE_MALLOC_TRIM
char* get_object_sseckey_md5(const char* path);
#endif // S3FS_S3_H_
#endif // S3FS_S3FS_H_
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
* vim600: expandtab sw=4 ts=4 fdm=marker
* vim<600: expandtab sw=4 ts=4
*/

View File

@ -1,7 +1,7 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright 2007-2008 Randy Rizun <rrizun@gmail.com>
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,30 +17,37 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef S3FS_AUTH_H_
#define S3FS_AUTH_H_
#include <string>
#include <sys/types.h>
//-------------------------------------------------------------------
// Utility functions for Authentication
//-------------------------------------------------------------------
//
// in common_auth.cpp
//
char* s3fs_base64(unsigned char* input, size_t length);
std::string s3fs_get_content_md5(int fd);
std::string s3fs_md5sum(int fd, off_t start, ssize_t size);
std::string s3fs_sha256_hex_fd(int fd, off_t start, off_t size);
//
// in xxxxxx_auth.cpp
//
const char* s3fs_crypt_lib_name(void);
bool s3fs_init_global_ssl(void);
bool s3fs_destroy_global_ssl(void);
bool s3fs_init_crypt_mutex(void);
bool s3fs_destroy_crypt_mutex(void);
const char* s3fs_crypt_lib_name();
bool s3fs_init_global_ssl();
bool s3fs_destroy_global_ssl();
bool s3fs_init_crypt_mutex();
bool s3fs_destroy_crypt_mutex();
bool s3fs_HMAC(const void* key, size_t keylen, const unsigned char* data, size_t datalen, unsigned char** digest, unsigned int* digestlen);
size_t get_md5_digest_length(void);
unsigned char* s3fs_md5hexsum(int fd, off_t start, ssize_t size);
bool s3fs_HMAC256(const void* key, size_t keylen, const unsigned char* data, size_t datalen, unsigned char** digest, unsigned int* digestlen);
size_t get_md5_digest_length();
unsigned char* s3fs_md5_fd(int fd, off_t start, off_t size);
bool s3fs_sha256(const unsigned char* data, size_t datalen, unsigned char** digest, unsigned int* digestlen);
size_t get_sha256_digest_length();
unsigned char* s3fs_sha256_fd(int fd, off_t start, off_t size);
#endif // S3FS_AUTH_H_
@ -49,6 +56,6 @@ unsigned char* s3fs_md5hexsum(int fd, off_t start, ssize_t size);
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
* vim600: expandtab sw=4 ts=4 fdm=marker
* vim<600: expandtab sw=4 ts=4
*/

48
src/s3fs_global.cpp Normal file
View File

@ -0,0 +1,48 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Takeshi Nakatani <ggtakec.com>
*
* 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 <sys/types.h>
#include <string>
//-------------------------------------------------------------------
// Global variables
//-------------------------------------------------------------------
bool foreground = false;
bool nomultipart = false;
bool pathrequeststyle = false;
bool complement_stat = false;
bool noxmlns = false;
std::string program_name;
std::string service_path = "/";
std::string s3host = "https://s3.amazonaws.com";
std::string bucket;
std::string endpoint = "us-east-1";
std::string cipher_suites;
std::string instance_name;
std::string aws_profile = "default";
/*
* 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
*/

577
src/s3fs_help.cpp Normal file
View File

@ -0,0 +1,577 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Takeshi Nakatani <ggtakec.com>
*
* 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 <cstdio>
#include <cstdlib>
#include <string>
#include "common.h"
#include "s3fs.h"
#include "s3fs_help.h"
#include "s3fs_auth.h"
//-------------------------------------------------------------------
// Contents
//-------------------------------------------------------------------
static const char help_string[] =
"\n"
"Mount an Amazon S3 bucket as a file system.\n"
"\n"
"Usage:\n"
" mounting\n"
" s3fs bucket[:/path] mountpoint [options]\n"
" s3fs mountpoint [options (must specify bucket= option)]\n"
"\n"
" unmounting\n"
" umount mountpoint\n"
"\n"
" General forms for s3fs and FUSE/mount options:\n"
" -o opt[,opt...]\n"
" -o opt [-o opt] ...\n"
"\n"
" utility mode (remove interrupted multipart uploading objects)\n"
" s3fs --incomplete-mpu-list (-u) bucket\n"
" s3fs --incomplete-mpu-abort[=all | =<date format>] bucket\n"
"\n"
"s3fs Options:\n"
"\n"
" Most s3fs options are given in the form where \"opt\" is:\n"
"\n"
" <option_name>=<option_value>\n"
"\n"
" bucket\n"
" - if it is not specified bucket name (and path) in command line,\n"
" must specify this option after -o option for bucket name.\n"
"\n"
" default_acl (default=\"private\")\n"
" - the default canned acl to apply to all written s3 objects,\n"
" e.g., private, public-read. see\n"
" https://docs.aws.amazon.com/AmazonS3/latest/dev/acl-overview.html#canned-acl\n"
" for the full list of canned acls\n"
"\n"
" retries (default=\"5\")\n"
" - number of times to retry a failed S3 transaction\n"
"\n"
" tmpdir (default=\"/tmp\")\n"
" - local folder for temporary files.\n"
"\n"
" use_cache (default=\"\" which means disabled)\n"
" - local folder to use for local file cache\n"
"\n"
" check_cache_dir_exist (default is disable)\n"
" - if use_cache is set, check if the cache directory exists.\n"
" If this option is not specified, it will be created at runtime\n"
" when the cache directory does not exist.\n"
"\n"
" del_cache (delete local file cache)\n"
" - delete local file cache when s3fs starts and exits.\n"
"\n"
" storage_class (default=\"standard\")\n"
" - store object with specified storage class. Possible values:\n"
" standard, standard_ia, onezone_ia, reduced_redundancy,\n"
" intelligent_tiering, glacier, and deep_archive.\n"
"\n"
" use_rrs (default is disable)\n"
" - use Amazon's Reduced Redundancy Storage.\n"
" this option can not be specified with use_sse.\n"
" (can specify use_rrs=1 for old version)\n"
" this option has been replaced by new storage_class option.\n"
"\n"
" use_sse (default is disable)\n"
" - Specify three type Amazon's Server-Site Encryption: SSE-S3,\n"
" SSE-C or SSE-KMS. SSE-S3 uses Amazon S3-managed encryption\n"
" keys, SSE-C uses customer-provided encryption keys, and\n"
" SSE-KMS uses the master key which you manage in AWS KMS.\n"
" You can specify \"use_sse\" or \"use_sse=1\" enables SSE-S3\n"
" type (use_sse=1 is old type parameter).\n"
" Case of setting SSE-C, you can specify \"use_sse=custom\",\n"
" \"use_sse=custom:<custom key file path>\" or\n"
" \"use_sse=<custom key file path>\" (only <custom key file path>\n"
" specified is old type parameter). You can use \"c\" for\n"
" short \"custom\".\n"
" The custom key file must be 600 permission. The file can\n"
" have some lines, each line is one SSE-C key. The first line\n"
" in file is used as Customer-Provided Encryption Keys for\n"
" uploading and changing headers etc. If there are some keys\n"
" after first line, those are used downloading object which\n"
" are encrypted by not first key. So that, you can keep all\n"
" SSE-C keys in file, that is SSE-C key history.\n"
" If you specify \"custom\" (\"c\") without file path, you\n"
" need to set custom key by load_sse_c option or AWSSSECKEYS\n"
" environment. (AWSSSECKEYS environment has some SSE-C keys\n"
" with \":\" separator.) This option is used to decide the\n"
" SSE type. So that if you do not want to encrypt a object\n"
" object at uploading, but you need to decrypt encrypted\n"
" object at downloading, you can use load_sse_c option instead\n"
" of this option.\n"
" For setting SSE-KMS, specify \"use_sse=kmsid\" or\n"
" \"use_sse=kmsid:<kms id>\". You can use \"k\" for short \"kmsid\".\n"
" If you san specify SSE-KMS type with your <kms id> in AWS\n"
" KMS, you can set it after \"kmsid:\" (or \"k:\"). If you\n"
" specify only \"kmsid\" (\"k\"), you need to set AWSSSEKMSID\n"
" environment which value is <kms id>. You must be careful\n"
" about that you can not use the KMS id which is not same EC2\n"
" region.\n"
"\n"
" load_sse_c - specify SSE-C keys\n"
" Specify the custom-provided encryption keys file path for decrypting\n"
" at downloading.\n"
" If you use the custom-provided encryption key at uploading, you\n"
" specify with \"use_sse=custom\". The file has many lines, one line\n"
" means one custom key. So that you can keep all SSE-C keys in file,\n"
" that is SSE-C key history. AWSSSECKEYS environment is as same as this\n"
" file contents.\n"
"\n"
" public_bucket (default=\"\" which means disabled)\n"
" - anonymously mount a public bucket when set to 1, ignores the \n"
" $HOME/.passwd-s3fs and /etc/passwd-s3fs files.\n"
" S3 does not allow copy object api for anonymous users, then\n"
" s3fs sets nocopyapi option automatically when public_bucket=1\n"
" option is specified.\n"
"\n"
" passwd_file (default=\"\")\n"
" - specify which s3fs password file to use\n"
"\n"
" ahbe_conf (default=\"\" which means disabled)\n"
" - This option specifies the configuration file path which\n"
" file is the additional HTTP header by file (object) extension.\n"
" The configuration file format is below:\n"
" -----------\n"
" line = [file suffix or regex] HTTP-header [HTTP-values]\n"
" file suffix = file (object) suffix, if this field is empty,\n"
" it means \"reg:(.*)\".(=all object).\n"
" regex = regular expression to match the file (object) path.\n"
" this type starts with \"reg:\" prefix.\n"
" HTTP-header = additional HTTP header name\n"
" HTTP-values = additional HTTP header value\n"
" -----------\n"
" Sample:\n"
" -----------\n"
" .gz Content-Encoding gzip\n"
" .Z Content-Encoding compress\n"
" reg:^/MYDIR/(.*)[.]t2$ Content-Encoding text2\n"
" -----------\n"
" A sample configuration file is uploaded in \"test\" directory.\n"
" If you specify this option for set \"Content-Encoding\" HTTP \n"
" header, please take care for RFC 2616.\n"
"\n"
" profile (default=\"default\")\n"
" - Choose a profile from ${HOME}/.aws/credentials to authenticate\n"
" against S3. Note that this format matches the AWS CLI format and\n"
" differs from the s3fs passwd format.\n"
"\n"
" connect_timeout (default=\"300\" seconds)\n"
" - time to wait for connection before giving up\n"
"\n"
" readwrite_timeout (default=\"120\" seconds)\n"
" - time to wait between read/write activity before giving up\n"
"\n"
" list_object_max_keys (default=\"1000\")\n"
" - specify the maximum number of keys returned by S3 list object\n"
" API. The default is 1000. you can set this value to 1000 or more.\n"
"\n"
" max_stat_cache_size (default=\"100,000\" entries (about 40MB))\n"
" - maximum number of entries in the stat cache, and this maximum is\n"
" also treated as the number of symbolic link cache.\n"
"\n"
" stat_cache_expire (default is 900))\n"
" - specify expire time (seconds) for entries in the stat cache.\n"
" This expire time indicates the time since stat cached. and this\n"
" is also set to the expire time of the symbolic link cache.\n"
"\n"
" stat_cache_interval_expire (default is 900)\n"
" - specify expire time (seconds) for entries in the stat cache(and\n"
" symbolic link cache).\n"
" This expire time is based on the time from the last access time\n"
" of the stat cache. This option is exclusive with stat_cache_expire,\n"
" and is left for compatibility with older versions.\n"
"\n"
" enable_noobj_cache (default is disable)\n"
" - enable cache entries for the object which does not exist.\n"
" s3fs always has to check whether file (or sub directory) exists \n"
" under object (path) when s3fs does some command, since s3fs has \n"
" recognized a directory which does not exist and has files or \n"
" sub directories under itself. It increases ListBucket request \n"
" and makes performance bad.\n"
" You can specify this option for performance, s3fs memorizes \n"
" in stat cache that the object (file or directory) does not exist.\n"
"\n"
" no_check_certificate\n"
" - server certificate won't be checked against the available \n"
" certificate authorities.\n"
"\n"
" ssl_verify_hostname (default=\"2\")\n"
" - When 0, do not verify the SSL certificate against the hostname.\n"
"\n"
" nodnscache (disable DNS cache)\n"
" - s3fs is always using DNS cache, this option make DNS cache disable.\n"
"\n"
" nosscache (disable SSL session cache)\n"
" - s3fs is always using SSL session cache, this option make SSL \n"
" session cache disable.\n"
"\n"
" multireq_max (default=\"20\")\n"
" - maximum number of parallel request for listing objects.\n"
"\n"
" parallel_count (default=\"5\")\n"
" - number of parallel request for uploading big objects.\n"
" s3fs uploads large object (over 20MB) by multipart post request, \n"
" and sends parallel requests.\n"
" This option limits parallel request count which s3fs requests \n"
" at once. It is necessary to set this value depending on a CPU \n"
" and a network band.\n"
"\n"
" multipart_size (default=\"10\")\n"
" - part size, in MB, for each multipart request.\n"
" The minimum value is 5 MB and the maximum value is 5 GB.\n"
"\n"
" multipart_copy_size (default=\"512\")\n"
" - part size, in MB, for each multipart copy request, used for\n"
" renames and mixupload.\n"
" The minimum value is 5 MB and the maximum value is 5 GB.\n"
" Must be at least 512 MB to copy the maximum 5 TB object size\n"
" but lower values may improve performance.\n"
"\n"
" max_dirty_data (default=\"5120\")\n"
" - flush dirty data to S3 after a certain number of MB written.\n"
" The minimum value is 50 MB. -1 value means disable.\n"
" Cannot be used with nomixupload.\n"
"\n"
" ensure_diskfree (default 0)\n"
" - sets MB to ensure disk free space. This option means the\n"
" threshold of free space size on disk which is used for the\n"
" cache file by s3fs. s3fs makes file for\n"
" downloading, uploading and caching files. If the disk free\n"
" space is smaller than this value, s3fs do not use diskspace\n"
" as possible in exchange for the performance.\n"
"\n"
" multipart_threshold (default=\"25\")\n"
" - threshold, in MB, to use multipart upload instead of\n"
" single-part. Must be at least 5 MB.\n"
"\n"
" singlepart_copy_limit (default=\"512\")\n"
" - maximum size, in MB, of a single-part copy before trying \n"
" multipart copy.\n"
"\n"
" host (default=\"https://s3.amazonaws.com\")\n"
" - Set a non-Amazon host, e.g., https://example.com.\n"
"\n"
" servicepath (default=\"/\")\n"
" - Set a service path when the non-Amazon host requires a prefix.\n"
"\n"
" url (default=\"https://s3.amazonaws.com\")\n"
" - sets the url to use to access Amazon S3. If you want to use HTTP,\n"
" then you can set \"url=http://s3.amazonaws.com\".\n"
" If you do not use https, please specify the URL with the url\n"
" option.\n"
"\n"
" endpoint (default=\"us-east-1\")\n"
" - sets the endpoint to use on signature version 4\n"
" If this option is not specified, s3fs uses \"us-east-1\" region as\n"
" the default. If the s3fs could not connect to the region specified\n"
" by this option, s3fs could not run. But if you do not specify this\n"
" option, and if you can not connect with the default region, s3fs\n"
" will retry to automatically connect to the other region. So s3fs\n"
" can know the correct region name, because s3fs can find it in an\n"
" error from the S3 server.\n"
"\n"
" sigv2 (default is signature version 4 falling back to version 2)\n"
" - sets signing AWS requests by using only signature version 2\n"
"\n"
" sigv4 (default is signature version 4 falling back to version 2)\n"
" - sets signing AWS requests by using only signature version 4\n"
"\n"
" mp_umask (default is \"0000\")\n"
" - sets umask for the mount point directory.\n"
" If allow_other option is not set, s3fs allows access to the mount\n"
" point only to the owner. In the opposite case s3fs allows access\n"
" to all users as the default. But if you set the allow_other with\n"
" this option, you can control the permissions of the\n"
" mount point by this option like umask.\n"
"\n"
" umask (default is \"0000\")\n"
" - sets umask for files under the mountpoint. This can allow\n"
" users other than the mounting user to read and write to files\n"
" that they did not create.\n"
"\n"
" nomultipart (disable multipart uploads)\n"
"\n"
" enable_content_md5 (default is disable)\n"
" Allow S3 server to check data integrity of uploads via the\n"
" Content-MD5 header. This can add CPU overhead to transfers.\n"
"\n"
" ecs (default is disable)\n"
" - This option instructs s3fs to query the ECS container credential\n"
" metadata address instead of the instance metadata address.\n"
"\n"
" iam_role (default is no IAM role)\n"
" - This option requires the IAM role name or \"auto\". If you specify\n"
" \"auto\", s3fs will automatically use the IAM role names that are set\n"
" to an instance. If you specify this option without any argument, it\n"
" is the same as that you have specified the \"auto\".\n"
"\n"
" imdsv1only (default is to use IMDSv2 with fallback to v1)\n"
" - AWS instance metadata service, used with IAM role authentication,\n"
" supports the use of an API token. If you're using an IAM role\n"
" in an environment that does not support IMDSv2, setting this flag\n"
" will skip retrieval and usage of the API token when retrieving\n"
" IAM credentials.\n"
"\n"
" ibm_iam_auth (default is not using IBM IAM authentication)\n"
" - This option instructs s3fs to use IBM IAM authentication.\n"
" In this mode, the AWSAccessKey and AWSSecretKey will be used as\n"
" IBM's Service-Instance-ID and APIKey, respectively.\n"
"\n"
" ibm_iam_endpoint (default is https://iam.cloud.ibm.com)\n"
" - sets the URL to use for IBM IAM authentication.\n"
"\n"
" use_xattr (default is not handling the extended attribute)\n"
" Enable to handle the extended attribute (xattrs).\n"
" If you set this option, you can use the extended attribute.\n"
" For example, encfs and ecryptfs need to support the extended attribute.\n"
" Notice: if s3fs handles the extended attribute, s3fs can not work to\n"
" copy command with preserve=mode.\n"
"\n"
" noxmlns (disable registering xml name space)\n"
" disable registering xml name space for response of \n"
" ListBucketResult and ListVersionsResult etc. Default name \n"
" space is looked up from \"http://s3.amazonaws.com/doc/2006-03-01\".\n"
" This option should not be specified now, because s3fs looks up\n"
" xmlns automatically after v1.66.\n"
"\n"
" nomixupload (disable copy in multipart uploads)\n"
" Disable to use PUT (copy api) when multipart uploading large size objects.\n"
" By default, when doing multipart upload, the range of unchanged data\n"
" will use PUT (copy api) whenever possible.\n"
" When nocopyapi or norenameapi is specified, use of PUT (copy api) is\n"
" invalidated even if this option is not specified.\n"
"\n"
" nocopyapi (for other incomplete compatibility object storage)\n"
" For a distributed object storage which is compatibility S3\n"
" API without PUT (copy api).\n"
" If you set this option, s3fs do not use PUT with \n"
" \"x-amz-copy-source\" (copy api). Because traffic is increased\n"
" 2-3 times by this option, we do not recommend this.\n"
"\n"
" norenameapi (for other incomplete compatibility object storage)\n"
" For a distributed object storage which is compatibility S3\n"
" API without PUT (copy api).\n"
" This option is a subset of nocopyapi option. The nocopyapi\n"
" option does not use copy-api for all command (ex. chmod, chown,\n"
" touch, mv, etc), but this option does not use copy-api for\n"
" only rename command (ex. mv). If this option is specified with\n"
" nocopyapi, then s3fs ignores it.\n"
"\n"
" use_path_request_style (use legacy API calling style)\n"
" Enable compatibility with S3-like APIs which do not support\n"
" the virtual-host request style, by using the older path request\n"
" style.\n"
"\n"
" listobjectsv2 (use ListObjectsV2)\n"
" Issue ListObjectsV2 instead of ListObjects, useful on object\n"
" stores without ListObjects support.\n"
"\n"
" noua (suppress User-Agent header)\n"
" Usually s3fs outputs of the User-Agent in \"s3fs/<version> (commit\n"
" hash <hash>; <using ssl library name>)\" format.\n"
" If this option is specified, s3fs suppresses the output of the\n"
" User-Agent.\n"
"\n"
" cipher_suites\n"
" Customize the list of TLS cipher suites.\n"
" Expects a colon separated list of cipher suite names.\n"
" A list of available cipher suites, depending on your TLS engine,\n"
" can be found on the CURL library documentation:\n"
" https://curl.haxx.se/docs/ssl-ciphers.html\n"
"\n"
" instance_name - The instance name of the current s3fs mountpoint.\n"
" This name will be added to logging messages and user agent headers sent by s3fs.\n"
"\n"
" complement_stat (complement lack of file/directory mode)\n"
" s3fs complements lack of information about file/directory mode\n"
" if a file or a directory object does not have x-amz-meta-mode\n"
" header. As default, s3fs does not complements stat information\n"
" for a object, then the object will not be able to be allowed to\n"
" list/modify.\n"
"\n"
" notsup_compat_dir (not support compatibility directory types)\n"
" As a default, s3fs supports objects of the directory type as\n"
" much as possible and recognizes them as directories.\n"
" Objects that can be recognized as directory objects are \"dir/\",\n"
" \"dir\", \"dir_$folder$\", and there is a file object that does\n"
" not have a directory object but contains that directory path.\n"
" s3fs needs redundant communication to support all these\n"
" directory types. The object as the directory created by s3fs\n"
" is \"dir/\". By restricting s3fs to recognize only \"dir/\" as\n"
" a directory, communication traffic can be reduced. This option\n"
" is used to give this restriction to s3fs.\n"
" However, if there is a directory object other than \"dir/\" in\n"
" the bucket, specifying this option is not recommended. s3fs may\n"
" not be able to recognize the object correctly if an object\n"
" created by s3fs exists in the bucket.\n"
" Please use this option when the directory in the bucket is\n"
" only \"dir/\" object.\n"
"\n"
" use_wtf8 - support arbitrary file system encoding.\n"
" S3 requires all object names to be valid UTF-8. But some\n"
" clients, notably Windows NFS clients, use their own encoding.\n"
" This option re-encodes invalid UTF-8 object names into valid\n"
" UTF-8 by mapping offending codes into a 'private' codepage of the\n"
" Unicode set.\n"
" Useful on clients not using UTF-8 as their file system encoding.\n"
"\n"
" use_session_token - indicate that session token should be provided.\n"
" If credentials are provided by environment variables this switch\n"
" forces presence check of AWSSESSIONTOKEN variable.\n"
" Otherwise an error is returned.\n"
"\n"
" requester_pays (default is disable)\n"
" This option instructs s3fs to enable requests involving\n"
" Requester Pays buckets.\n"
" It includes the 'x-amz-request-payer=requester' entry in the\n"
" request header.\n"
"\n"
" mime (default is \"/etc/mime.types\")\n"
" Specify the path of the mime.types file.\n"
" If this option is not specified, the existence of \"/etc/mime.types\"\n"
" is checked, and that file is loaded as mime information.\n"
" If this file does not exist on macOS, then \"/etc/apache2/mime.types\"\n"
" is checked as well.\n"
"\n"
" logfile - specify the log output file.\n"
" s3fs outputs the log file to syslog. Alternatively, if s3fs is\n"
" started with the \"-f\" option specified, the log will be output\n"
" to the stdout/stderr.\n"
" You can use this option to specify the log file that s3fs outputs.\n"
" If you specify a log file with this option, it will reopen the log\n"
" file when s3fs receives a SIGHUP signal. You can use the SIGHUP\n"
" signal for log rotation.\n"
"\n"
" dbglevel (default=\"crit\")\n"
" Set the debug message level. set value as crit (critical), err\n"
" (error), warn (warning), info (information) to debug level.\n"
" default debug level is critical. If s3fs run with \"-d\" option,\n"
" the debug level is set information. When s3fs catch the signal\n"
" SIGUSR2, the debug level is bumpup.\n"
"\n"
" curldbg - put curl debug message\n"
" Put the debug message from libcurl when this option is specified.\n"
" Specify \"normal\" or \"body\" for the parameter.\n"
" If the parameter is omitted, it is the same as \"normal\".\n"
" If \"body\" is specified, some API communication body data will be\n"
" output in addition to the debug message output as \"normal\".\n"
"\n"
" no_time_stamp_msg - no time stamp in debug message\n"
" The time stamp is output to the debug message by default.\n"
" If this option is specified, the time stamp will not be output\n"
" in the debug message.\n"
" It is the same even if the environment variable \"S3FS_MSGTIMESTAMP\"\n"
" is set to \"no\".\n"
"\n"
" set_check_cache_sigusr1 (default is stdout)\n"
" If the cache is enabled, you can check the integrity of the\n"
" cache file and the cache file's stats info file.\n"
" This option is specified and when sending the SIGUSR1 signal\n"
" to the s3fs process checks the cache status at that time.\n"
" This option can take a file path as parameter to output the\n"
" check result to that file. The file path parameter can be omitted.\n"
" If omitted, the result will be output to stdout or syslog.\n"
"\n"
"FUSE/mount Options:\n"
"\n"
" Most of the generic mount options described in 'man mount' are\n"
" supported (ro, rw, suid, nosuid, dev, nodev, exec, noexec, atime,\n"
" noatime, sync async, dirsync). Filesystems are mounted with\n"
" '-onodev,nosuid' by default, which can only be overridden by a\n"
" privileged user.\n"
" \n"
" There are many FUSE specific mount options that can be specified.\n"
" e.g. allow_other See the FUSE's README for the full set.\n"
"\n"
"Utility mode Options:\n"
"\n"
" -u, --incomplete-mpu-list\n"
" Lists multipart incomplete objects uploaded to the specified\n"
" bucket.\n"
" --incomplete-mpu-abort (=all or =<date format>)\n"
" Delete the multipart incomplete object uploaded to the specified\n"
" bucket.\n"
" If \"all\" is specified for this option, all multipart incomplete\n"
" objects will be deleted. If you specify no argument as an option,\n"
" objects older than 24 hours (24H) will be deleted (This is the\n"
" default value). You can specify an optional date format. It can\n"
" be specified as year, month, day, hour, minute, second, and it is\n"
" expressed as \"Y\", \"M\", \"D\", \"h\", \"m\", \"s\" respectively.\n"
" For example, \"1Y6M10D12h30m30s\".\n"
"\n"
"Miscellaneous Options:\n"
"\n"
" -h, --help Output this help.\n"
" --version Output version info.\n"
" -d --debug Turn on DEBUG messages to syslog. Specifying -d\n"
" twice turns on FUSE debug messages to STDOUT.\n"
" -f FUSE foreground option - do not run as daemon.\n"
" -s FUSE single-threaded option\n"
" disable multi-threaded operation\n"
"\n"
"\n"
"s3fs home page: <https://github.com/s3fs-fuse/s3fs-fuse>\n"
;
//-------------------------------------------------------------------
// Functions
//-------------------------------------------------------------------
void show_usage()
{
printf("Usage: %s BUCKET:[PATH] MOUNTPOINT [OPTION]...\n", program_name.c_str());
}
void show_help()
{
show_usage();
printf(help_string);
}
void show_version()
{
printf(
"Amazon Simple Storage Service File System V%s (commit:%s) with %s\n"
"Copyright (C) 2010 Randy Rizun <rrizun@gmail.com>\n"
"License GPL2: GNU GPL version 2 <https://gnu.org/licenses/gpl.html>\n"
"This is free software: you are free to change and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.\n",
VERSION, COMMIT_HASH_VAL, s3fs_crypt_lib_name());
}
const char* short_version()
{
static const char short_ver[] = "s3fs version " VERSION "(" COMMIT_HASH_VAL ")";
return short_ver;
}
/*
* 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
*/

41
src/s3fs_help.h Normal file
View File

@ -0,0 +1,41 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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.
*/
#ifndef S3FS_S3FS_HELP_H_
#define S3FS_S3FS_HELP_H_
//-------------------------------------------------------------------
// Functions
//-------------------------------------------------------------------
void show_usage();
void show_help();
void show_version();
const char* short_version();
#endif // S3FS_S3FS_HELP_H_
/*
* 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
*/

267
src/s3fs_logger.cpp Normal file
View File

@ -0,0 +1,267 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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 <cstdlib>
#include <iomanip>
#include <sstream>
#include <string>
#include "common.h"
#include "s3fs_logger.h"
//-------------------------------------------------------------------
// S3fsLog class : variables
//-------------------------------------------------------------------
const int S3fsLog::NEST_MAX;
const char* const S3fsLog::nest_spaces[S3fsLog::NEST_MAX] = {"", " ", " ", " "};
const char S3fsLog::LOGFILEENV[] = "S3FS_LOGFILE";
const char S3fsLog::MSGTIMESTAMP[] = "S3FS_MSGTIMESTAMP";
S3fsLog* S3fsLog::pSingleton = NULL;
S3fsLog::s3fs_log_level S3fsLog::debug_level = S3fsLog::LEVEL_CRIT;
FILE* S3fsLog::logfp = NULL;
std::string* S3fsLog::plogfile = NULL;
bool S3fsLog::time_stamp = true;
//-------------------------------------------------------------------
// S3fsLog class : class methods
//-------------------------------------------------------------------
bool S3fsLog::IsS3fsLogLevel(s3fs_log_level level)
{
return (level == (S3fsLog::debug_level & level));
}
std::string S3fsLog::GetCurrentTime()
{
std::ostringstream current_time;
if(time_stamp){
struct timeval now;
struct timespec tsnow;
struct tm res;
char tmp[32];
if(-1 == clock_gettime(S3FS_CLOCK_MONOTONIC, &tsnow)){
now.tv_sec = tsnow.tv_sec;
now.tv_usec = (tsnow.tv_nsec / 1000);
}else{
gettimeofday(&now, NULL);
}
strftime(tmp, sizeof(tmp), "%Y-%m-%dT%H:%M:%S", gmtime_r(&now.tv_sec, &res));
current_time << tmp << "." << std::setfill('0') << std::setw(3) << (now.tv_usec / 1000) << "Z ";
}
return current_time.str();
}
bool S3fsLog::SetLogfile(const char* pfile)
{
if(!S3fsLog::pSingleton){
S3FS_PRN_CRIT("S3fsLog::pSingleton is NULL.");
return false;
}
return S3fsLog::pSingleton->LowSetLogfile(pfile);
}
bool S3fsLog::ReopenLogfile()
{
if(!S3fsLog::pSingleton){
S3FS_PRN_CRIT("S3fsLog::pSingleton is NULL.");
return false;
}
if(!S3fsLog::logfp){
S3FS_PRN_INFO("Currently the log file is output to stdout/stderr.");
return true;
}
if(!S3fsLog::plogfile){
S3FS_PRN_ERR("There is a problem with the path to the log file being NULL.");
return false;
}
std::string tmp = *(S3fsLog::plogfile);
return S3fsLog::pSingleton->LowSetLogfile(tmp.c_str());
}
S3fsLog::s3fs_log_level S3fsLog::SetLogLevel(s3fs_log_level level)
{
if(!S3fsLog::pSingleton){
S3FS_PRN_CRIT("S3fsLog::pSingleton is NULL.");
return S3fsLog::debug_level; // Although it is an error, it returns the current value.
}
return S3fsLog::pSingleton->LowSetLogLevel(level);
}
S3fsLog::s3fs_log_level S3fsLog::BumpupLogLevel()
{
if(!S3fsLog::pSingleton){
S3FS_PRN_CRIT("S3fsLog::pSingleton is NULL.");
return S3fsLog::debug_level; // Although it is an error, it returns the current value.
}
return S3fsLog::pSingleton->LowBumpupLogLevel();
}
bool S3fsLog::SetTimeStamp(bool value)
{
bool old = S3fsLog::time_stamp;
S3fsLog::time_stamp = value;
return old;
}
//-------------------------------------------------------------------
// S3fsLog class : methods
//-------------------------------------------------------------------
S3fsLog::S3fsLog()
{
if(!S3fsLog::pSingleton){
S3fsLog::pSingleton = this;
// init syslog(default CRIT)
openlog("s3fs", LOG_PID | LOG_ODELAY | LOG_NOWAIT, LOG_USER);
LowLoadEnv();
}else{
S3FS_PRN_ERR("Already set singleton object for S3fsLog.");
}
}
S3fsLog::~S3fsLog()
{
if(S3fsLog::pSingleton == this){
FILE* oldfp = S3fsLog::logfp;
S3fsLog::logfp = NULL;
if(oldfp && 0 != fclose(oldfp)){
S3FS_PRN_ERR("Could not close old log file(%s), but continue...", (S3fsLog::plogfile ? S3fsLog::plogfile->c_str() : "null"));
}
if(S3fsLog::plogfile){
delete S3fsLog::plogfile;
S3fsLog::plogfile = NULL;
}
S3fsLog::pSingleton = NULL;
S3fsLog::debug_level = S3fsLog::LEVEL_CRIT;
closelog();
}else{
S3FS_PRN_ERR("This object is not singleton S3fsLog object.");
}
}
bool S3fsLog::LowLoadEnv()
{
if(S3fsLog::pSingleton != this){
S3FS_PRN_ERR("This object is not as same as S3fsLog::pSingleton.");
return false;
}
char* pEnvVal;
if(NULL != (pEnvVal = getenv(S3fsLog::LOGFILEENV))){
if(!SetLogfile(pEnvVal)){
return false;
}
}
if(NULL != (pEnvVal = getenv(S3fsLog::MSGTIMESTAMP))){
if(0 == strcasecmp(pEnvVal, "true") || 0 == strcasecmp(pEnvVal, "yes") || 0 == strcasecmp(pEnvVal, "1")){
S3fsLog::time_stamp = true;
}else if(0 == strcasecmp(pEnvVal, "false") || 0 == strcasecmp(pEnvVal, "no") || 0 == strcasecmp(pEnvVal, "0")){
S3fsLog::time_stamp = false;
}else{
S3FS_PRN_WARN("Unknown %s environment value(%s) is specified, skip to set time stamp mode.", S3fsLog::MSGTIMESTAMP, pEnvVal);
}
}
return true;
}
bool S3fsLog::LowSetLogfile(const char* pfile)
{
if(S3fsLog::pSingleton != this){
S3FS_PRN_ERR("This object is not as same as S3fsLog::pSingleton.");
return false;
}
if(!pfile){
// close log file if it is opened
if(S3fsLog::logfp && 0 != fclose(S3fsLog::logfp)){
S3FS_PRN_ERR("Could not close log file(%s).", (S3fsLog::plogfile ? S3fsLog::plogfile->c_str() : "null"));
return false;
}
S3fsLog::logfp = NULL;
if(S3fsLog::plogfile){
delete S3fsLog::plogfile;
S3fsLog::plogfile = NULL;
}
}else{
// open new log file
//
// [NOTE]
// It will reopen even if it is the same file.
//
FILE* newfp;
if(NULL == (newfp = fopen(pfile, "a+"))){
S3FS_PRN_ERR("Could not open log file(%s).", pfile);
return false;
}
// switch new log file and close old log file if it is opened
FILE* oldfp = S3fsLog::logfp;
S3fsLog::logfp = newfp;
if(oldfp && 0 != fclose(oldfp)){
S3FS_PRN_ERR("Could not close old log file(%s).", (S3fsLog::plogfile ? S3fsLog::plogfile->c_str() : "null"));
S3fsLog::logfp = oldfp;
fclose(newfp);
return false;
}
delete S3fsLog::plogfile;
S3fsLog::plogfile = new std::string(pfile);
}
return true;
}
S3fsLog::s3fs_log_level S3fsLog::LowSetLogLevel(s3fs_log_level level)
{
if(S3fsLog::pSingleton != this){
S3FS_PRN_ERR("This object is not as same as S3fsLog::pSingleton.");
return S3fsLog::debug_level; // Although it is an error, it returns the current value.
}
if(level == S3fsLog::debug_level){
return S3fsLog::debug_level;
}
s3fs_log_level old = S3fsLog::debug_level;
S3fsLog::debug_level = level;
setlogmask(LOG_UPTO(GetSyslogLevel(S3fsLog::debug_level)));
S3FS_PRN_CRIT("change debug level from %sto %s", GetLevelString(old), GetLevelString(S3fsLog::debug_level));
return old;
}
S3fsLog::s3fs_log_level S3fsLog::LowBumpupLogLevel()
{
if(S3fsLog::pSingleton != this){
S3FS_PRN_ERR("This object is not as same as S3fsLog::pSingleton.");
return S3fsLog::debug_level; // Although it is an error, it returns the current value.
}
s3fs_log_level old = S3fsLog::debug_level;
S3fsLog::debug_level = ( LEVEL_CRIT == S3fsLog::debug_level ? LEVEL_ERR :
LEVEL_ERR == S3fsLog::debug_level ? LEVEL_WARN :
LEVEL_WARN == S3fsLog::debug_level ? LEVEL_INFO :
LEVEL_INFO == S3fsLog::debug_level ? LEVEL_DBG : LEVEL_CRIT );
setlogmask(LOG_UPTO(GetSyslogLevel(S3fsLog::debug_level)));
S3FS_PRN_CRIT("change debug level from %sto %s", GetLevelString(old), GetLevelString(S3fsLog::debug_level));
return old;
}
/*
* 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
*/

252
src/s3fs_logger.h Normal file
View File

@ -0,0 +1,252 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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.
*/
#ifndef S3FS_LOGGER_H_
#define S3FS_LOGGER_H_
#include <cstdio>
#include <syslog.h>
#include <sys/time.h>
#ifdef CLOCK_MONOTONIC_COARSE
#define S3FS_CLOCK_MONOTONIC CLOCK_MONOTONIC_COARSE
#else
// case of OSX
#define S3FS_CLOCK_MONOTONIC CLOCK_MONOTONIC
#endif
//-------------------------------------------------------------------
// S3fsLog class
//-------------------------------------------------------------------
class S3fsLog
{
public:
enum s3fs_log_level{
LEVEL_CRIT = 0, // LEVEL_CRIT
LEVEL_ERR = 1, // LEVEL_ERR
LEVEL_WARN = 3, // LEVEL_WARNING
LEVEL_INFO = 7, // LEVEL_INFO
LEVEL_DBG = 15 // LEVEL_DEBUG
};
protected:
static const int NEST_MAX = 4;
static const char* const nest_spaces[NEST_MAX];
static const char LOGFILEENV[];
static const char MSGTIMESTAMP[];
static S3fsLog* pSingleton;
static s3fs_log_level debug_level;
static FILE* logfp;
static std::string* plogfile;
static bool time_stamp;
protected:
bool LowLoadEnv();
bool LowSetLogfile(const char* pfile);
s3fs_log_level LowSetLogLevel(s3fs_log_level level);
s3fs_log_level LowBumpupLogLevel();
public:
static bool IsS3fsLogLevel(s3fs_log_level level);
static bool IsS3fsLogCrit() { return IsS3fsLogLevel(LEVEL_CRIT); }
static bool IsS3fsLogErr() { return IsS3fsLogLevel(LEVEL_ERR); }
static bool IsS3fsLogWarn() { return IsS3fsLogLevel(LEVEL_WARN); }
static bool IsS3fsLogInfo() { return IsS3fsLogLevel(LEVEL_INFO); }
static bool IsS3fsLogDbg() { return IsS3fsLogLevel(LEVEL_DBG); }
static int GetSyslogLevel(s3fs_log_level level)
{
return ( LEVEL_DBG == (level & LEVEL_DBG) ? LOG_DEBUG :
LEVEL_INFO == (level & LEVEL_DBG) ? LOG_INFO :
LEVEL_WARN == (level & LEVEL_DBG) ? LOG_WARNING :
LEVEL_ERR == (level & LEVEL_DBG) ? LOG_ERR : LOG_CRIT );
}
static std::string GetCurrentTime();
static const char* GetLevelString(s3fs_log_level level)
{
return ( LEVEL_DBG == (level & LEVEL_DBG) ? "[DBG] " :
LEVEL_INFO == (level & LEVEL_DBG) ? "[INF] " :
LEVEL_WARN == (level & LEVEL_DBG) ? "[WAN] " :
LEVEL_ERR == (level & LEVEL_DBG) ? "[ERR] " : "[CRT] " );
}
static const char* GetS3fsLogNest(int nest)
{
if(nest < NEST_MAX){
return nest_spaces[nest];
}else{
return nest_spaces[NEST_MAX - 1];
}
}
static bool IsSetLogFile()
{
return (NULL != logfp);
}
static FILE* GetOutputLogFile()
{
return (logfp ? logfp : stdout);
}
static FILE* GetErrorLogFile()
{
return (logfp ? logfp : stderr);
}
static void SeekEnd()
{
if(logfp){
fseek(logfp, 0, SEEK_END);
}
}
static void Flush()
{
if(logfp){
fflush(logfp);
}
}
static bool SetLogfile(const char* pfile);
static bool ReopenLogfile();
static s3fs_log_level SetLogLevel(s3fs_log_level level);
static s3fs_log_level BumpupLogLevel();
static bool SetTimeStamp(bool value);
explicit S3fsLog();
~S3fsLog();
};
//-------------------------------------------------------------------
// Debug macros
//-------------------------------------------------------------------
#define S3FS_LOW_LOGPRN(level, fmt, ...) \
do{ \
if(S3fsLog::IsS3fsLogLevel(level)){ \
if(foreground || S3fsLog::IsSetLogFile()){ \
S3fsLog::SeekEnd(); \
fprintf(S3fsLog::GetOutputLogFile(), "%s%s%s:%s(%d): " fmt "%s\n", S3fsLog::GetCurrentTime().c_str(), S3fsLog::GetLevelString(level), __FILE__, __func__, __LINE__, __VA_ARGS__); \
S3fsLog::Flush(); \
}else{ \
syslog(S3fsLog::GetSyslogLevel(level), "%s%s:%s(%d): " fmt "%s", instance_name.c_str(), __FILE__, __func__, __LINE__, __VA_ARGS__); \
} \
} \
}while(0)
#define S3FS_LOW_LOGPRN2(level, nest, fmt, ...) \
do{ \
if(S3fsLog::IsS3fsLogLevel(level)){ \
if(foreground || S3fsLog::IsSetLogFile()){ \
S3fsLog::SeekEnd(); \
fprintf(S3fsLog::GetOutputLogFile(), "%s%s%s%s:%s(%d): " fmt "%s\n", S3fsLog::GetCurrentTime().c_str(), S3fsLog::GetLevelString(level), S3fsLog::GetS3fsLogNest(nest), __FILE__, __func__, __LINE__, __VA_ARGS__); \
S3fsLog::Flush(); \
}else{ \
syslog(S3fsLog::GetSyslogLevel(level), "%s%s" fmt "%s", instance_name.c_str(), S3fsLog::GetS3fsLogNest(nest), __VA_ARGS__); \
} \
} \
}while(0)
#define S3FS_LOW_CURLDBG(fmt, ...) \
do{ \
if(foreground || S3fsLog::IsSetLogFile()){ \
S3fsLog::SeekEnd(); \
fprintf(S3fsLog::GetOutputLogFile(), "%s[CURL DBG] " fmt "%s\n", S3fsLog::GetCurrentTime().c_str(), __VA_ARGS__); \
S3fsLog::Flush(); \
}else{ \
syslog(S3fsLog::GetSyslogLevel(S3fsLog::LEVEL_CRIT), "%s" fmt "%s", instance_name.c_str(), __VA_ARGS__); \
} \
}while(0)
#define S3FS_LOW_LOGPRN_EXIT(fmt, ...) \
do{ \
if(foreground || S3fsLog::IsSetLogFile()){ \
S3fsLog::SeekEnd(); \
fprintf(S3fsLog::GetErrorLogFile(), "s3fs: " fmt "%s\n", __VA_ARGS__); \
S3fsLog::Flush(); \
}else{ \
fprintf(S3fsLog::GetErrorLogFile(), "s3fs: " fmt "%s\n", __VA_ARGS__); \
syslog(S3fsLog::GetSyslogLevel(S3fsLog::LEVEL_CRIT), "%ss3fs: " fmt "%s", instance_name.c_str(), __VA_ARGS__); \
} \
}while(0)
// Special macro for init message
#define S3FS_PRN_INIT_INFO(fmt, ...) \
do{ \
if(foreground || S3fsLog::IsSetLogFile()){ \
S3fsLog::SeekEnd(); \
fprintf(S3fsLog::GetOutputLogFile(), "%s%s%s%s:%s(%d): " fmt "%s\n", S3fsLog::GetCurrentTime().c_str(), S3fsLog::GetLevelString(S3fsLog::LEVEL_INFO), S3fsLog::GetS3fsLogNest(0), __FILE__, __func__, __LINE__, __VA_ARGS__, ""); \
S3fsLog::Flush(); \
}else{ \
syslog(S3fsLog::GetSyslogLevel(S3fsLog::LEVEL_INFO), "%s%s" fmt "%s", instance_name.c_str(), S3fsLog::GetS3fsLogNest(0), __VA_ARGS__, ""); \
} \
}while(0)
#define S3FS_PRN_LAUNCH_INFO(fmt, ...) \
do{ \
if(foreground || S3fsLog::IsSetLogFile()){ \
S3fsLog::SeekEnd(); \
fprintf(S3fsLog::GetOutputLogFile(), "%s%s" fmt "%s\n", S3fsLog::GetCurrentTime().c_str(), S3fsLog::GetLevelString(S3fsLog::LEVEL_INFO), __VA_ARGS__, ""); \
S3fsLog::Flush(); \
}else{ \
syslog(S3fsLog::GetSyslogLevel(S3fsLog::LEVEL_INFO), "%s" fmt "%s", instance_name.c_str(), __VA_ARGS__, ""); \
} \
}while(0)
// Special macro for checking cache files
#define S3FS_LOW_CACHE(fp, fmt, ...) \
do{ \
if(foreground || S3fsLog::IsSetLogFile()){ \
S3fsLog::SeekEnd(); \
fprintf(fp, fmt "%s\n", __VA_ARGS__); \
S3fsLog::Flush(); \
}else{ \
syslog(S3fsLog::GetSyslogLevel(S3fsLog::LEVEL_INFO), "%s: " fmt "%s", instance_name.c_str(), __VA_ARGS__); \
} \
}while(0)
// [NOTE]
// small trick for VA_ARGS
//
#define S3FS_PRN_EXIT(fmt, ...) S3FS_LOW_LOGPRN_EXIT(fmt, ##__VA_ARGS__, "")
#define S3FS_PRN_CRIT(fmt, ...) S3FS_LOW_LOGPRN(S3fsLog::LEVEL_CRIT, fmt, ##__VA_ARGS__, "")
#define S3FS_PRN_ERR(fmt, ...) S3FS_LOW_LOGPRN(S3fsLog::LEVEL_ERR, fmt, ##__VA_ARGS__, "")
#define S3FS_PRN_WARN(fmt, ...) S3FS_LOW_LOGPRN(S3fsLog::LEVEL_WARN, fmt, ##__VA_ARGS__, "")
#define S3FS_PRN_DBG(fmt, ...) S3FS_LOW_LOGPRN(S3fsLog::LEVEL_DBG, fmt, ##__VA_ARGS__, "")
#define S3FS_PRN_INFO(fmt, ...) S3FS_LOW_LOGPRN2(S3fsLog::LEVEL_INFO, 0, fmt, ##__VA_ARGS__, "")
#define S3FS_PRN_INFO1(fmt, ...) S3FS_LOW_LOGPRN2(S3fsLog::LEVEL_INFO, 1, fmt, ##__VA_ARGS__, "")
#define S3FS_PRN_INFO2(fmt, ...) S3FS_LOW_LOGPRN2(S3fsLog::LEVEL_INFO, 2, fmt, ##__VA_ARGS__, "")
#define S3FS_PRN_INFO3(fmt, ...) S3FS_LOW_LOGPRN2(S3fsLog::LEVEL_INFO, 3, fmt, ##__VA_ARGS__, "")
#define S3FS_PRN_CURL(fmt, ...) S3FS_LOW_CURLDBG(fmt, ##__VA_ARGS__, "")
#define S3FS_PRN_CACHE(fp, ...) S3FS_LOW_CACHE(fp, ##__VA_ARGS__, "")
#endif // S3FS_LOGGER_H_
/*
* 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
*/

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright 2007-2008 Randy Rizun <rrizun@gmail.com>
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,123 +17,32 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef S3FS_S3FS_UTIL_H_
#define S3FS_S3FS_UTIL_H_
//-------------------------------------------------------------------
// Typedef
//-------------------------------------------------------------------
//
// Struct
//
struct s3obj_entry{
std::string normalname; // normalized name: if empty, object is nomalized name.
std::string orgname; // original name: if empty, object is original name.
std::string etag;
bool is_dir;
s3obj_entry() : is_dir(false) {}
};
typedef std::map<std::string, struct s3obj_entry> s3obj_t;
typedef std::list<std::string> s3obj_list_t;
//
// Class
//
class S3ObjList
{
private:
s3obj_t objects;
private:
bool insert_nomalized(const char* name, const char* normalized, bool is_dir);
const s3obj_entry* GetS3Obj(const char* name) const;
s3obj_t::const_iterator begin(void) const {
return objects.begin();
}
s3obj_t::const_iterator end(void) const {
return objects.end();
}
public:
S3ObjList() {}
~S3ObjList() {}
bool IsEmpty(void) const {
return objects.empty();
}
bool insert(const char* name, const char* etag = NULL, bool is_dir = false);
std::string GetOrgName(const char* name) const;
std::string GetNormalizedName(const char* name) const;
std::string GetETag(const char* name) const;
bool IsDir(const char* name) const;
bool GetNameList(s3obj_list_t& list, bool OnlyNormalized = true, bool CutSlash = true) const;
bool GetLastName(std::string& lastname) const;
static bool MakeHierarchizedList(s3obj_list_t& list, bool haveSlash);
};
typedef struct mvnode {
char *old_path;
char *new_path;
bool is_dir;
bool is_normdir;
struct mvnode *prev;
struct mvnode *next;
} MVNODE;
class AutoLock
{
private:
pthread_mutex_t* auto_mutex;
bool is_locked;
public:
AutoLock(pthread_mutex_t* pmutex = NULL);
~AutoLock();
bool Lock(void);
bool Unlock(void);
};
//-------------------------------------------------------------------
// Functions
//-------------------------------------------------------------------
std::string get_realpath(const char *path);
MVNODE *create_mvnode(const char *old_path, const char *new_path, bool is_dir, bool normdir = false);
MVNODE *add_mvnode(MVNODE** head, MVNODE** tail, const char *old_path, const char *new_path, bool is_dir, bool normdir = false);
void free_mvnodes(MVNODE *head);
void init_sysconf_vars();
std::string get_username(uid_t uid);
int is_uid_inculde_group(uid_t uid, gid_t gid);
int is_uid_include_group(uid_t uid, gid_t gid);
std::string mydirname(const char* path);
std::string mydirname(const std::string& path);
std::string mybasename(const char* path);
std::string mybasename(const std::string& path);
std::string mydirname(std::string path);
std::string mybasename(std::string path);
int mkdirp(const std::string& path, mode_t mode);
std::string get_exist_directory_path(const std::string& path);
bool check_exist_dir_permission(const char* dirpath);
bool delete_files_in_dir(const char* dir, bool is_remove_own);
time_t get_mtime(const char *s);
time_t get_mtime(headers_t& meta, bool overcheck = true);
off_t get_size(const char *s);
off_t get_size(headers_t& meta);
mode_t get_mode(const char *s);
mode_t get_mode(headers_t& meta, const char* path = NULL, bool checkdir = false, bool forcedir = false);
uid_t get_uid(const char *s);
uid_t get_uid(headers_t& meta);
gid_t get_gid(const char *s);
gid_t get_gid(headers_t& meta);
blkcnt_t get_blocks(off_t size);
time_t cvtIAMExpireStringToTime(const char* s);
time_t get_lastmodified(const char* s);
time_t get_lastmodified(headers_t& meta);
bool is_need_check_obj_detail(headers_t& meta);
bool compare_sysname(const char* target);
void show_usage(void);
void show_help(void);
void show_version(void);
void print_launch_message(int argc, char** argv);
#endif // S3FS_S3FS_UTIL_H_
@ -142,6 +51,6 @@ void show_version(void);
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
* vim600: expandtab sw=4 ts=4 fdm=marker
* vim<600: expandtab sw=4 ts=4
*/

502
src/s3fs_xml.cpp Normal file
View File

@ -0,0 +1,502 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Takeshi Nakatani <ggtakec.com>
*
* 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 <cstdio>
#include <cstdlib>
#include "common.h"
#include "s3fs.h"
#include "s3fs_xml.h"
#include "s3fs_util.h"
//-------------------------------------------------------------------
// Variables
//-------------------------------------------------------------------
static const char c_strErrorObjectName[] = "FILE or SUBDIR in DIR";
//-------------------------------------------------------------------
// Functions
//-------------------------------------------------------------------
static bool GetXmlNsUrl(xmlDocPtr doc, std::string& nsurl)
{
static time_t tmLast = 0; // cache for 60 sec.
static std::string strNs;
bool result = false;
if(!doc){
return false;
}
if((tmLast + 60) < time(NULL)){
// refresh
tmLast = time(NULL);
strNs = "";
xmlNodePtr pRootNode = xmlDocGetRootElement(doc);
if(pRootNode){
xmlNsPtr* nslist = xmlGetNsList(doc, pRootNode);
if(nslist){
if(nslist[0] && nslist[0]->href){
strNs = (const char*)(nslist[0]->href);
}
S3FS_XMLFREE(nslist);
}
}
}
if(!strNs.empty()){
nsurl = strNs;
result = true;
}
return result;
}
static xmlChar* get_base_exp(xmlDocPtr doc, const char* exp)
{
xmlXPathObjectPtr marker_xp;
std::string xmlnsurl;
std::string exp_string;
if(!doc){
return NULL;
}
xmlXPathContextPtr ctx = xmlXPathNewContext(doc);
if(!noxmlns && GetXmlNsUrl(doc, xmlnsurl)){
xmlXPathRegisterNs(ctx, (xmlChar*)"s3", (xmlChar*)xmlnsurl.c_str());
exp_string = "/s3:ListBucketResult/s3:";
} else {
exp_string = "/ListBucketResult/";
}
exp_string += exp;
if(NULL == (marker_xp = xmlXPathEvalExpression((xmlChar *)exp_string.c_str(), ctx))){
xmlXPathFreeContext(ctx);
return NULL;
}
if(xmlXPathNodeSetIsEmpty(marker_xp->nodesetval)){
S3FS_PRN_ERR("marker_xp->nodesetval is empty.");
xmlXPathFreeObject(marker_xp);
xmlXPathFreeContext(ctx);
return NULL;
}
xmlNodeSetPtr nodes = marker_xp->nodesetval;
xmlChar* result = xmlNodeListGetString(doc, nodes->nodeTab[0]->xmlChildrenNode, 1);
xmlXPathFreeObject(marker_xp);
xmlXPathFreeContext(ctx);
return result;
}
static xmlChar* get_prefix(xmlDocPtr doc)
{
return get_base_exp(doc, "Prefix");
}
xmlChar* get_next_continuation_token(xmlDocPtr doc)
{
return get_base_exp(doc, "NextContinuationToken");
}
xmlChar* get_next_marker(xmlDocPtr doc)
{
return get_base_exp(doc, "NextMarker");
}
// return: the pointer to object name on allocated memory.
// the pointer to "c_strErrorObjectName".(not allocated)
// NULL(a case of something error occurred)
static char* get_object_name(xmlDocPtr doc, xmlNodePtr node, const char* path)
{
// Get full path
xmlChar* fullpath = xmlNodeListGetString(doc, node, 1);
if(!fullpath){
S3FS_PRN_ERR("could not get object full path name..");
return NULL;
}
// basepath(path) is as same as fullpath.
if(0 == strcmp((char*)fullpath, path)){
xmlFree(fullpath);
return (char*)c_strErrorObjectName;
}
// Make dir path and filename
std::string strdirpath = mydirname(std::string((char*)fullpath));
std::string strmybpath = mybasename(std::string((char*)fullpath));
const char* dirpath = strdirpath.c_str();
const char* mybname = strmybpath.c_str();
const char* basepath= (path && '/' == path[0]) ? &path[1] : path;
xmlFree(fullpath);
if(!mybname || '\0' == mybname[0]){
return NULL;
}
// check subdir & file in subdir
if(dirpath && 0 < strlen(dirpath)){
// case of "/"
if(0 == strcmp(mybname, "/") && 0 == strcmp(dirpath, "/")){
return (char*)c_strErrorObjectName;
}
// case of "."
if(0 == strcmp(mybname, ".") && 0 == strcmp(dirpath, ".")){
return (char*)c_strErrorObjectName;
}
// case of ".."
if(0 == strcmp(mybname, "..") && 0 == strcmp(dirpath, ".")){
return (char*)c_strErrorObjectName;
}
// case of "name"
if(0 == strcmp(dirpath, ".")){
// OK
return strdup(mybname);
}else{
if(basepath && 0 == strcmp(dirpath, basepath)){
// OK
return strdup(mybname);
}else if(basepath && 0 < strlen(basepath) && '/' == basepath[strlen(basepath) - 1] && 0 == strncmp(dirpath, basepath, strlen(basepath) - 1)){
std::string withdirname;
if(strlen(dirpath) > strlen(basepath)){
withdirname = &dirpath[strlen(basepath)];
}
if(!withdirname.empty() && '/' != *withdirname.rbegin()){
withdirname += "/";
}
withdirname += mybname;
return strdup(withdirname.c_str());
}
}
}
// case of something wrong
return (char*)c_strErrorObjectName;
}
static xmlChar* get_exp_value_xml(xmlDocPtr doc, xmlXPathContextPtr ctx, const char* exp_key)
{
if(!doc || !ctx || !exp_key){
return NULL;
}
xmlXPathObjectPtr exp;
xmlNodeSetPtr exp_nodes;
xmlChar* exp_value;
// search exp_key tag
if(NULL == (exp = xmlXPathEvalExpression((xmlChar*)exp_key, ctx))){
S3FS_PRN_ERR("Could not find key(%s).", exp_key);
return NULL;
}
if(xmlXPathNodeSetIsEmpty(exp->nodesetval)){
S3FS_PRN_ERR("Key(%s) node is empty.", exp_key);
S3FS_XMLXPATHFREEOBJECT(exp);
return NULL;
}
// get exp_key value & set in struct
exp_nodes = exp->nodesetval;
if(NULL == (exp_value = xmlNodeListGetString(doc, exp_nodes->nodeTab[0]->xmlChildrenNode, 1))){
S3FS_PRN_ERR("Key(%s) value is empty.", exp_key);
S3FS_XMLXPATHFREEOBJECT(exp);
return NULL;
}
S3FS_XMLXPATHFREEOBJECT(exp);
return exp_value;
}
bool get_incomp_mpu_list(xmlDocPtr doc, incomp_mpu_list_t& list)
{
if(!doc){
return false;
}
xmlXPathContextPtr ctx = xmlXPathNewContext(doc);;
std::string xmlnsurl;
std::string ex_upload = "//";
std::string ex_key;
std::string ex_id;
std::string ex_date;
if(!noxmlns && GetXmlNsUrl(doc, xmlnsurl)){
xmlXPathRegisterNs(ctx, (xmlChar*)"s3", (xmlChar*)xmlnsurl.c_str());
ex_upload += "s3:";
ex_key += "s3:";
ex_id += "s3:";
ex_date += "s3:";
}
ex_upload += "Upload";
ex_key += "Key";
ex_id += "UploadId";
ex_date += "Initiated";
// get "Upload" Tags
xmlXPathObjectPtr upload_xp;
if(NULL == (upload_xp = xmlXPathEvalExpression((xmlChar*)ex_upload.c_str(), ctx))){
S3FS_PRN_ERR("xmlXPathEvalExpression returns null.");
return false;
}
if(xmlXPathNodeSetIsEmpty(upload_xp->nodesetval)){
S3FS_PRN_INFO("upload_xp->nodesetval is empty.");
S3FS_XMLXPATHFREEOBJECT(upload_xp);
S3FS_XMLXPATHFREECONTEXT(ctx);
return true;
}
// Make list
int cnt;
xmlNodeSetPtr upload_nodes;
list.clear();
for(cnt = 0, upload_nodes = upload_xp->nodesetval; cnt < upload_nodes->nodeNr; cnt++){
ctx->node = upload_nodes->nodeTab[cnt];
INCOMP_MPU_INFO part;
xmlChar* ex_value;
// search "Key" tag
if(NULL == (ex_value = get_exp_value_xml(doc, ctx, ex_key.c_str()))){
continue;
}
if('/' != *((char*)ex_value)){
part.key = "/";
}else{
part.key = "";
}
part.key += (char*)ex_value;
S3FS_XMLFREE(ex_value);
// search "UploadId" tag
if(NULL == (ex_value = get_exp_value_xml(doc, ctx, ex_id.c_str()))){
continue;
}
part.id = (char*)ex_value;
S3FS_XMLFREE(ex_value);
// search "Initiated" tag
if(NULL == (ex_value = get_exp_value_xml(doc, ctx, ex_date.c_str()))){
continue;
}
part.date = (char*)ex_value;
S3FS_XMLFREE(ex_value);
list.push_back(part);
}
S3FS_XMLXPATHFREEOBJECT(upload_xp);
S3FS_XMLXPATHFREECONTEXT(ctx);
return true;
}
bool is_truncated(xmlDocPtr doc)
{
bool result = false;
xmlChar* strTruncate = get_base_exp(doc, "IsTruncated");
if(!strTruncate){
return false;
}
if(0 == strcasecmp((const char*)strTruncate, "true")){
result = true;
}
xmlFree(strTruncate);
return result;
}
int append_objects_from_xml_ex(const char* path, xmlDocPtr doc, xmlXPathContextPtr ctx, const char* ex_contents, const char* ex_key, const char* ex_etag, int isCPrefix, S3ObjList& head)
{
xmlXPathObjectPtr contents_xp;
xmlNodeSetPtr content_nodes;
if(NULL == (contents_xp = xmlXPathEvalExpression((xmlChar*)ex_contents, ctx))){
S3FS_PRN_ERR("xmlXPathEvalExpression returns null.");
return -1;
}
if(xmlXPathNodeSetIsEmpty(contents_xp->nodesetval)){
S3FS_PRN_DBG("contents_xp->nodesetval is empty.");
S3FS_XMLXPATHFREEOBJECT(contents_xp);
return 0;
}
content_nodes = contents_xp->nodesetval;
bool is_dir;
std::string stretag;
int i;
for(i = 0; i < content_nodes->nodeNr; i++){
ctx->node = content_nodes->nodeTab[i];
// object name
xmlXPathObjectPtr key;
if(NULL == (key = xmlXPathEvalExpression((xmlChar*)ex_key, ctx))){
S3FS_PRN_WARN("key is null. but continue.");
continue;
}
if(xmlXPathNodeSetIsEmpty(key->nodesetval)){
S3FS_PRN_WARN("node is empty. but continue.");
xmlXPathFreeObject(key);
continue;
}
xmlNodeSetPtr key_nodes = key->nodesetval;
char* name = get_object_name(doc, key_nodes->nodeTab[0]->xmlChildrenNode, path);
if(!name){
S3FS_PRN_WARN("name is something wrong. but continue.");
}else if((const char*)name != c_strErrorObjectName){
is_dir = isCPrefix ? true : false;
stretag = "";
if(!isCPrefix && ex_etag){
// Get ETag
xmlXPathObjectPtr ETag;
if(NULL != (ETag = xmlXPathEvalExpression((xmlChar*)ex_etag, ctx))){
if(xmlXPathNodeSetIsEmpty(ETag->nodesetval)){
S3FS_PRN_INFO("ETag->nodesetval is empty.");
}else{
xmlNodeSetPtr etag_nodes = ETag->nodesetval;
xmlChar* petag = xmlNodeListGetString(doc, etag_nodes->nodeTab[0]->xmlChildrenNode, 1);
if(petag){
stretag = (char*)petag;
xmlFree(petag);
}
}
xmlXPathFreeObject(ETag);
}
}
if(!head.insert(name, (!stretag.empty() ? stretag.c_str() : NULL), is_dir)){
S3FS_PRN_ERR("insert_object returns with error.");
xmlXPathFreeObject(key);
xmlXPathFreeObject(contents_xp);
free(name);
S3FS_MALLOCTRIM(0);
return -1;
}
free(name);
}else{
S3FS_PRN_DBG("name is file or subdir in dir. but continue.");
}
xmlXPathFreeObject(key);
}
S3FS_XMLXPATHFREEOBJECT(contents_xp);
return 0;
}
int append_objects_from_xml(const char* path, xmlDocPtr doc, S3ObjList& head)
{
std::string xmlnsurl;
std::string ex_contents = "//";
std::string ex_key;
std::string ex_cprefix = "//";
std::string ex_prefix;
std::string ex_etag;
if(!doc){
return -1;
}
// If there is not <Prefix>, use path instead of it.
xmlChar* pprefix = get_prefix(doc);
std::string prefix = (pprefix ? (char*)pprefix : path ? path : "");
if(pprefix){
xmlFree(pprefix);
}
xmlXPathContextPtr ctx = xmlXPathNewContext(doc);
if(!noxmlns && GetXmlNsUrl(doc, xmlnsurl)){
xmlXPathRegisterNs(ctx, (xmlChar*)"s3", (xmlChar*)xmlnsurl.c_str());
ex_contents+= "s3:";
ex_key += "s3:";
ex_cprefix += "s3:";
ex_prefix += "s3:";
ex_etag += "s3:";
}
ex_contents+= "Contents";
ex_key += "Key";
ex_cprefix += "CommonPrefixes";
ex_prefix += "Prefix";
ex_etag += "ETag";
if(-1 == append_objects_from_xml_ex(prefix.c_str(), doc, ctx, ex_contents.c_str(), ex_key.c_str(), ex_etag.c_str(), 0, head) ||
-1 == append_objects_from_xml_ex(prefix.c_str(), doc, ctx, ex_cprefix.c_str(), ex_prefix.c_str(), NULL, 1, head) )
{
S3FS_PRN_ERR("append_objects_from_xml_ex returns with error.");
S3FS_XMLXPATHFREECONTEXT(ctx);
return -1;
}
S3FS_XMLXPATHFREECONTEXT(ctx);
return 0;
}
//-------------------------------------------------------------------
// Utility functions
//-------------------------------------------------------------------
bool simple_parse_xml(const char* data, size_t len, const char* key, std::string& value)
{
bool result = false;
if(!data || !key){
return false;
}
value.clear();
xmlDocPtr doc;
if(NULL == (doc = xmlReadMemory(data, static_cast<int>(len), "", NULL, 0))){
return false;
}
if(NULL == doc->children){
S3FS_XMLFREEDOC(doc);
return false;
}
for(xmlNodePtr cur_node = doc->children->children; NULL != cur_node; cur_node = cur_node->next){
// For DEBUG
// std::string cur_node_name(reinterpret_cast<const char *>(cur_node->name));
// printf("cur_node_name: %s\n", cur_node_name.c_str());
if(XML_ELEMENT_NODE == cur_node->type){
std::string elementName = reinterpret_cast<const char*>(cur_node->name);
// For DEBUG
// printf("elementName: %s\n", elementName.c_str());
if(cur_node->children){
if(XML_TEXT_NODE == cur_node->children->type){
if(elementName == key) {
value = reinterpret_cast<const char *>(cur_node->children->content);
result = true;
break;
}
}
}
}
}
S3FS_XMLFREEDOC(doc);
return result;
}
/*
* 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
*/

54
src/s3fs_xml.h Normal file
View File

@ -0,0 +1,54 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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.
*/
#ifndef S3FS_S3FS_XML_H_
#define S3FS_S3FS_XML_H_
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
#include <libxml/tree.h>
#include <string>
#include "s3objlist.h"
#include "mpu_util.h"
//-------------------------------------------------------------------
// Functions
//-------------------------------------------------------------------
bool is_truncated(xmlDocPtr doc);
int append_objects_from_xml_ex(const char* path, xmlDocPtr doc, xmlXPathContextPtr ctx, const char* ex_contents, const char* ex_key, const char* ex_etag, int isCPrefix, S3ObjList& head);
int append_objects_from_xml(const char* path, xmlDocPtr doc, S3ObjList& head);
xmlChar* get_next_continuation_token(xmlDocPtr doc);
xmlChar* get_next_marker(xmlDocPtr doc);
bool get_incomp_mpu_list(xmlDocPtr doc, incomp_mpu_list_t& list);
bool simple_parse_xml(const char* data, size_t len, const char* key, std::string& value);
#endif // S3FS_S3FS_XML_H_
/*
* 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
*/

284
src/s3objlist.cpp Normal file
View File

@ -0,0 +1,284 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Takeshi Nakatani <ggtakec.com>
*
* 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 <cstdio>
#include <cstdlib>
#include "common.h"
#include "s3fs.h"
#include "s3objlist.h"
//-------------------------------------------------------------------
// Class S3ObjList
//-------------------------------------------------------------------
// New class S3ObjList is base on old s3_object struct.
// This class is for S3 compatible clients.
//
// If name is terminated by "/", it is forced dir type.
// If name is terminated by "_$folder$", it is forced dir type.
// If is_dir is true and name is not terminated by "/", the name is added "/".
//
bool S3ObjList::insert(const char* name, const char* etag, bool is_dir)
{
if(!name || '\0' == name[0]){
return false;
}
s3obj_t::iterator iter;
std::string newname;
std::string orgname = name;
// Normalization
std::string::size_type pos = orgname.find("_$folder$");
if(std::string::npos != pos){
newname = orgname.substr(0, pos);
is_dir = true;
}else{
newname = orgname;
}
if(is_dir){
if('/' != *newname.rbegin()){
newname += "/";
}
}else{
if('/' == *newname.rbegin()){
is_dir = true;
}
}
// Check derived name object.
if(is_dir){
std::string chkname = newname.substr(0, newname.length() - 1);
if(objects.end() != (iter = objects.find(chkname))){
// found "dir" object --> remove it.
objects.erase(iter);
}
}else{
std::string chkname = newname + "/";
if(objects.end() != (iter = objects.find(chkname))){
// found "dir/" object --> not add new object.
// and add normalization
return insert_normalized(orgname.c_str(), chkname.c_str(), true);
}
}
// Add object
if(objects.end() != (iter = objects.find(newname))){
// Found same object --> update information.
(*iter).second.normalname.erase();
(*iter).second.orgname = orgname;
(*iter).second.is_dir = is_dir;
if(etag){
(*iter).second.etag = std::string(etag); // over write
}
}else{
// add new object
s3obj_entry newobject;
newobject.orgname = orgname;
newobject.is_dir = is_dir;
if(etag){
newobject.etag = etag;
}
objects[newname] = newobject;
}
// add normalization
return insert_normalized(orgname.c_str(), newname.c_str(), is_dir);
}
bool S3ObjList::insert_normalized(const char* name, const char* normalized, bool is_dir)
{
if(!name || '\0' == name[0] || !normalized || '\0' == normalized[0]){
return false;
}
if(0 == strcmp(name, normalized)){
return true;
}
s3obj_t::iterator iter;
if(objects.end() != (iter = objects.find(name))){
// found name --> over write
iter->second.orgname.erase();
iter->second.etag.erase();
iter->second.normalname = normalized;
iter->second.is_dir = is_dir;
}else{
// not found --> add new object
s3obj_entry newobject;
newobject.normalname = normalized;
newobject.is_dir = is_dir;
objects[name] = newobject;
}
return true;
}
const s3obj_entry* S3ObjList::GetS3Obj(const char* name) const
{
s3obj_t::const_iterator iter;
if(!name || '\0' == name[0]){
return NULL;
}
if(objects.end() == (iter = objects.find(name))){
return NULL;
}
return &((*iter).second);
}
std::string S3ObjList::GetOrgName(const char* name) const
{
const s3obj_entry* ps3obj;
if(!name || '\0' == name[0]){
return std::string("");
}
if(NULL == (ps3obj = GetS3Obj(name))){
return std::string("");
}
return ps3obj->orgname;
}
std::string S3ObjList::GetNormalizedName(const char* name) const
{
const s3obj_entry* ps3obj;
if(!name || '\0' == name[0]){
return std::string("");
}
if(NULL == (ps3obj = GetS3Obj(name))){
return std::string("");
}
if(ps3obj->normalname.empty()){
return std::string(name);
}
return ps3obj->normalname;
}
std::string S3ObjList::GetETag(const char* name) const
{
const s3obj_entry* ps3obj;
if(!name || '\0' == name[0]){
return std::string("");
}
if(NULL == (ps3obj = GetS3Obj(name))){
return std::string("");
}
return ps3obj->etag;
}
bool S3ObjList::IsDir(const char* name) const
{
const s3obj_entry* ps3obj;
if(NULL == (ps3obj = GetS3Obj(name))){
return false;
}
return ps3obj->is_dir;
}
bool S3ObjList::GetLastName(std::string& lastname) const
{
bool result = false;
lastname = "";
for(s3obj_t::const_iterator iter = objects.begin(); iter != objects.end(); ++iter){
if((*iter).second.orgname.length()){
if(0 > strcmp(lastname.c_str(), (*iter).second.orgname.c_str())){
lastname = (*iter).second.orgname;
result = true;
}
}else{
if(0 > strcmp(lastname.c_str(), (*iter).second.normalname.c_str())){
lastname = (*iter).second.normalname;
result = true;
}
}
}
return result;
}
bool S3ObjList::GetNameList(s3obj_list_t& list, bool OnlyNormalized, bool CutSlash) const
{
s3obj_t::const_iterator iter;
for(iter = objects.begin(); objects.end() != iter; ++iter){
if(OnlyNormalized && !iter->second.normalname.empty()){
continue;
}
std::string name = (*iter).first;
if(CutSlash && 1 < name.length() && '/' == *name.rbegin()){
// only "/" std::string is skipped this.
name.erase(name.length() - 1);
}
list.push_back(name);
}
return true;
}
typedef std::map<std::string, bool> s3obj_h_t;
bool S3ObjList::MakeHierarchizedList(s3obj_list_t& list, bool haveSlash)
{
s3obj_h_t h_map;
s3obj_h_t::iterator hiter;
s3obj_list_t::const_iterator liter;
for(liter = list.begin(); list.end() != liter; ++liter){
std::string strtmp = (*liter);
if(1 < strtmp.length() && '/' == *strtmp.rbegin()){
strtmp.erase(strtmp.length() - 1);
}
h_map[strtmp] = true;
// check hierarchized directory
for(std::string::size_type pos = strtmp.find_last_of('/'); std::string::npos != pos; pos = strtmp.find_last_of('/')){
strtmp.erase(pos);
if(strtmp.empty() || "/" == strtmp){
break;
}
if(h_map.end() == h_map.find(strtmp)){
// not found
h_map[strtmp] = false;
}
}
}
// check map and add lost hierarchized directory.
for(hiter = h_map.begin(); hiter != h_map.end(); ++hiter){
if(false == (*hiter).second){
// add hierarchized directory.
std::string strtmp = (*hiter).first;
if(haveSlash){
strtmp += "/";
}
list.push_back(strtmp);
}
}
return true;
}
/*
* 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
*/

79
src/s3objlist.h Normal file
View File

@ -0,0 +1,79 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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.
*/
#ifndef S3FS_S3OBJLIST_H_
#define S3FS_S3OBJLIST_H_
//-------------------------------------------------------------------
// Structure / Typedef
//-------------------------------------------------------------------
struct s3obj_entry{
std::string normalname; // normalized name: if empty, object is normalized name.
std::string orgname; // original name: if empty, object is original name.
std::string etag;
bool is_dir;
s3obj_entry() : is_dir(false) {}
};
typedef std::map<std::string, struct s3obj_entry> s3obj_t;
typedef std::list<std::string> s3obj_list_t;
//-------------------------------------------------------------------
// Class S3ObjList
//-------------------------------------------------------------------
class S3ObjList
{
private:
s3obj_t objects;
private:
bool insert_normalized(const char* name, const char* normalized, bool is_dir);
const s3obj_entry* GetS3Obj(const char* name) const;
s3obj_t::const_iterator begin() const { return objects.begin(); }
s3obj_t::const_iterator end() const { return objects.end(); }
public:
S3ObjList() {}
~S3ObjList() {}
bool IsEmpty() const { return objects.empty(); }
bool insert(const char* name, const char* etag = NULL, bool is_dir = false);
std::string GetOrgName(const char* name) const;
std::string GetNormalizedName(const char* name) const;
std::string GetETag(const char* name) const;
bool IsDir(const char* name) const;
bool GetNameList(s3obj_list_t& list, bool OnlyNormalized = true, bool CutSlash = true) const;
bool GetLastName(std::string& lastname) const;
static bool MakeHierarchizedList(s3obj_list_t& list, bool haveSlash);
};
#endif // S3FS_S3OBJLIST_H_
/*
* 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
*/

271
src/sighandlers.cpp Normal file
View File

@ -0,0 +1,271 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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 <cstdio>
#include <cstdlib>
#include <csignal>
#include <pthread.h>
#include "common.h"
#include "s3fs.h"
#include "sighandlers.h"
#include "fdcache.h"
//-------------------------------------------------------------------
// Class S3fsSignals
//-------------------------------------------------------------------
S3fsSignals* S3fsSignals::pSingleton = NULL;
bool S3fsSignals::enableUsr1 = false;
//-------------------------------------------------------------------
// Class methods
//-------------------------------------------------------------------
bool S3fsSignals::Initialize()
{
if(!S3fsSignals::pSingleton){
S3fsSignals::pSingleton = new S3fsSignals;
}
return true;
}
bool S3fsSignals::Destroy()
{
delete S3fsSignals::pSingleton;
S3fsSignals::pSingleton = NULL;
return true;
}
void S3fsSignals::HandlerUSR1(int sig)
{
if(SIGUSR1 != sig){
S3FS_PRN_ERR("The handler for SIGUSR1 received signal(%d)", sig);
return;
}
S3fsSignals* pSigobj = S3fsSignals::get();
if(!pSigobj){
S3FS_PRN_ERR("S3fsSignals object is not initialized.");
return;
}
if(!pSigobj->WakeupUsr1Thread()){
S3FS_PRN_ERR("Failed to wakeup the thread for SIGUSR1.");
return;
}
}
bool S3fsSignals::SetUsr1Handler(const char* path)
{
if(!FdManager::HaveLseekHole()){
S3FS_PRN_ERR("Could not set SIGUSR1 for checking cache, because this system does not support SEEK_DATA/SEEK_HOLE in lseek function.");
return false;
}
// set output file
if(!FdManager::SetCacheCheckOutput(path)){
S3FS_PRN_ERR("Could not set output file(%s) for checking cache.", path ? path : "null(stdout)");
return false;
}
S3fsSignals::enableUsr1 = true;
return true;
}
void* S3fsSignals::CheckCacheWorker(void* arg)
{
Semaphore* pSem = static_cast<Semaphore*>(arg);
if(!pSem){
pthread_exit(NULL);
}
if(!S3fsSignals::enableUsr1){
pthread_exit(NULL);
}
// wait and loop
while(S3fsSignals::enableUsr1){
// wait
pSem->wait();
if(!S3fsSignals::enableUsr1){
break; // assap
}
// check all cache
if(!FdManager::get()->CheckAllCache()){
S3FS_PRN_ERR("Processing failed due to some problem.");
}
// do not allow request queuing
for(int value = pSem->get_value(); 0 < value; value = pSem->get_value()){
pSem->wait();
}
}
return NULL;
}
void S3fsSignals::HandlerUSR2(int sig)
{
if(SIGUSR2 == sig){
S3fsLog::BumpupLogLevel();
}else{
S3FS_PRN_ERR("The handler for SIGUSR2 received signal(%d)", sig);
}
}
bool S3fsSignals::InitUsr2Handler()
{
struct sigaction sa;
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_handler = S3fsSignals::HandlerUSR2;
sa.sa_flags = SA_RESTART;
if(0 != sigaction(SIGUSR2, &sa, NULL)){
return false;
}
return true;
}
void S3fsSignals::HandlerHUP(int sig)
{
if(SIGHUP == sig){
S3fsLog::ReopenLogfile();
}else{
S3FS_PRN_ERR("The handler for SIGHUP received signal(%d)", sig);
}
}
bool S3fsSignals::InitHupHandler()
{
struct sigaction sa;
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_handler = S3fsSignals::HandlerHUP;
sa.sa_flags = SA_RESTART;
if(0 != sigaction(SIGHUP, &sa, NULL)){
return false;
}
return true;
}
//-------------------------------------------------------------------
// Methods
//-------------------------------------------------------------------
S3fsSignals::S3fsSignals() : pThreadUsr1(NULL), pSemUsr1(NULL)
{
if(S3fsSignals::enableUsr1){
if(!InitUsr1Handler()){
S3FS_PRN_ERR("failed creating thread for SIGUSR1 handler, but continue...");
}
}
if(!S3fsSignals::InitUsr2Handler()){
S3FS_PRN_ERR("failed to initialize SIGUSR2 handler for bumping log level, but continue...");
}
if(!S3fsSignals::InitHupHandler()){
S3FS_PRN_ERR("failed to initialize SIGHUP handler for reopen log file, but continue...");
}
}
S3fsSignals::~S3fsSignals()
{
if(S3fsSignals::enableUsr1){
if(!DestroyUsr1Handler()){
S3FS_PRN_ERR("failed stopping thread for SIGUSR1 handler, but continue...");
}
}
}
bool S3fsSignals::InitUsr1Handler()
{
if(pThreadUsr1 || pSemUsr1){
S3FS_PRN_ERR("Already run thread for SIGUSR1");
return false;
}
// create thread
int result;
pSemUsr1 = new Semaphore(0);
pThreadUsr1 = new pthread_t;
if(0 != (result = pthread_create(pThreadUsr1, NULL, S3fsSignals::CheckCacheWorker, static_cast<void*>(pSemUsr1)))){
S3FS_PRN_ERR("Could not create thread for SIGUSR1 by %d", result);
delete pSemUsr1;
delete pThreadUsr1;
pSemUsr1 = NULL;
pThreadUsr1 = NULL;
return false;
}
// set handler
struct sigaction sa;
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_handler = S3fsSignals::HandlerUSR1;
sa.sa_flags = SA_RESTART;
if(0 != sigaction(SIGUSR1, &sa, NULL)){
S3FS_PRN_ERR("Could not set signal handler for SIGUSR1");
DestroyUsr1Handler();
return false;
}
return true;
}
bool S3fsSignals::DestroyUsr1Handler()
{
if(!pThreadUsr1 || !pSemUsr1){
return false;
}
// for thread exit
S3fsSignals::enableUsr1 = false;
// wakeup thread
pSemUsr1->post();
// wait for thread exiting
void* retval = NULL;
int result;
if(0 != (result = pthread_join(*pThreadUsr1, &retval))){
S3FS_PRN_ERR("Could not stop thread for SIGUSR1 by %d", result);
return false;
}
delete pSemUsr1;
delete pThreadUsr1;
pSemUsr1 = NULL;
pThreadUsr1 = NULL;
return true;
}
bool S3fsSignals::WakeupUsr1Thread()
{
if(!pThreadUsr1 || !pSemUsr1){
S3FS_PRN_ERR("The thread for SIGUSR1 is not setup.");
return false;
}
pSemUsr1->post();
return true;
}
/*
* 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
*/

73
src/sighandlers.h Normal file
View File

@ -0,0 +1,73 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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.
*/
#ifndef S3FS_SIGHANDLERS_H_
#define S3FS_SIGHANDLERS_H_
#include "psemaphore.h"
//----------------------------------------------
// class S3fsSignals
//----------------------------------------------
class S3fsSignals
{
private:
static S3fsSignals* pSingleton;
static bool enableUsr1;
pthread_t* pThreadUsr1;
Semaphore* pSemUsr1;
protected:
static S3fsSignals* get() { return pSingleton; }
static void HandlerUSR1(int sig);
static void* CheckCacheWorker(void* arg);
static void HandlerUSR2(int sig);
static bool InitUsr2Handler();
static void HandlerHUP(int sig);
static bool InitHupHandler();
S3fsSignals();
~S3fsSignals();
bool InitUsr1Handler();
bool DestroyUsr1Handler();
bool WakeupUsr1Thread();
public:
static bool Initialize();
static bool Destroy();
static bool SetUsr1Handler(const char* path);
};
#endif // S3FS_SIGHANDLERS_H_
/*
* 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
*/

View File

@ -1,7 +1,7 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright 2007-2008 Randy Rizun <rrizun@gmail.com>
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,205 +17,580 @@
* 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 <string.h>
#include <syslog.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cerrno>
#include <climits>
#include <iomanip>
#include <stdexcept>
#include <sstream>
#include <string>
#include <map>
#include "common.h"
#include "s3fs.h"
#include "string_util.h"
using namespace std;
//-------------------------------------------------------------------
// Global variables
//-------------------------------------------------------------------
const char SPACES[] = " \t\r\n";
static const char hexAlphabet[] = "0123456789ABCDEF";
off_t s3fs_strtoofft(const char* str, bool is_base_16)
//-------------------------------------------------------------------
// Templates
//-------------------------------------------------------------------
template <class T> std::string str(T value)
{
if(!str || '\0' == *str){
return 0;
}
off_t result;
bool chk_space;
bool chk_base16_prefix;
for(result = 0, chk_space = false, chk_base16_prefix = false; '\0' != *str; str++){
// check head space
if(!chk_space && isspace(*str)){
continue;
}else if(!chk_space){
chk_space = true;
std::ostringstream s;
s << value;
return s.str();
}
template std::string str(short value);
template std::string str(unsigned short value);
template std::string str(int value);
template std::string str(unsigned int value);
template std::string str(long value);
template std::string str(unsigned long value);
template std::string str(long long value);
template std::string str(unsigned long long value);
template<> std::string str(struct timespec value) {
std::ostringstream s;
s << value.tv_sec;
if(value.tv_nsec != 0){
s << "." << std::setfill('0') << std::setw(9) << value.tv_nsec;
}
// check prefix for base 16
if(!chk_base16_prefix){
chk_base16_prefix = true;
if('0' == *str && ('x' == str[1] || 'X' == str[1])){
is_base_16 = true;
str++;
continue;
}
return s.str();
}
//-------------------------------------------------------------------
// Functions
//-------------------------------------------------------------------
bool s3fs_strtoofft(off_t* value, const char* str, int base)
{
if(value == NULL || str == NULL){
return false;
}
// check like isalnum and set data
result *= (is_base_16 ? 16 : 10);
if('0' <= *str || '9' < *str){
result += static_cast<off_t>(*str - '0');
}else if(is_base_16){
if('A' <= *str && *str <= 'F'){
result += static_cast<off_t>(*str - 'A' + 0x0a);
}else if('a' <= *str && *str <= 'f'){
result += static_cast<off_t>(*str - 'a' + 0x0a);
}else{
errno = 0;
char *temp;
long long result = strtoll(str, &temp, base);
if(temp == str || *temp != '\0'){
return false;
}
if((result == LLONG_MIN || result == LLONG_MAX) && errno == ERANGE){
return false;
}
*value = result;
return true;
}
off_t cvt_strtoofft(const char* str, int base)
{
off_t result = 0;
if(!s3fs_strtoofft(&result, str, base)){
S3FS_PRN_WARN("something error is occurred in convert std::string(%s) to off_t, thus return 0 as default.", (str ? str : "null"));
return 0;
}
}
return result;
}
std::string lower(std::string s)
{
// change each character of the std::string to lower case
for(size_t i = 0; i < s.length(); i++){
s[i] = tolower(s[i]);
}
return s;
}
std::string trim_left(const std::string &s, const char *t /* = SPACES */)
{
std::string d(s);
return d.erase(0, s.find_first_not_of(t));
}
std::string trim_right(const std::string &s, const char *t /* = SPACES */)
{
std::string d(s);
std::string::size_type i(d.find_last_not_of(t));
if(i == std::string::npos){
return "";
}else{
return 0;
return d.erase(d.find_last_not_of(t) + 1);
}
}
return result;
}
string lower(string s)
std::string trim(const std::string &s, const char *t /* = SPACES */)
{
// change each character of the string to lower case
for(unsigned int i = 0; i < s.length(); i++){
s[i] = tolower(s[i]);
}
return s;
return trim_left(trim_right(s, t), t);
}
string IntToStr(int n)
//
// urlEncode a fuse path,
// taking into special consideration "/",
// otherwise regular urlEncode.
//
std::string urlEncode(const std::string &s)
{
stringstream result;
result << n;
return result.str();
}
string trim_left(const string &s, const string &t /* = SPACES */)
{
string d(s);
return d.erase(0, s.find_first_not_of(t));
}
string trim_right(const string &s, const string &t /* = SPACES */)
{
string d(s);
string::size_type i(d.find_last_not_of(t));
if(i == string::npos){
return "";
}else{
return d.erase(d.find_last_not_of(t) + 1);
}
}
string trim(const string &s, const string &t /* = SPACES */)
{
string d(s);
return trim_left(trim_right(d, t), t);
}
/**
* urlEncode a fuse path,
* taking into special consideration "/",
* otherwise regular urlEncode.
*/
string urlEncode(const string &s)
{
string result;
for (unsigned i = 0; i < s.length(); ++i) {
if (s[i] == '/') { // Note- special case for fuse paths...
result += s[i];
} else if (isalnum(s[i])) {
result += s[i];
} else if (s[i] == '.' || s[i] == '-' || s[i] == '*' || s[i] == '_') {
result += s[i];
} else if (s[i] == ' ') {
result += '%';
result += '2';
result += '0';
} else {
result += "%";
result += hexAlphabet[static_cast<unsigned char>(s[i]) / 16];
result += hexAlphabet[static_cast<unsigned char>(s[i]) % 16];
std::string result;
for (size_t i = 0; i < s.length(); ++i) {
unsigned char c = s[i];
if (c == '/' // Note- special case for fuse paths...
|| c == '.'
|| c == '-'
|| c == '_'
|| c == '~'
|| (c >= 'a' && c <= 'z')
|| (c >= 'A' && c <= 'Z')
|| (c >= '0' && c <= '9'))
{
result += c;
}else{
result += "%";
result += s3fs_hex_upper(&c, 1);
}
}
}
return result;
}
return result;
//
// urlEncode a fuse path,
// taking into special consideration "/",
// otherwise regular urlEncode.
//
std::string urlEncode2(const std::string &s)
{
std::string result;
for (size_t i = 0; i < s.length(); ++i) {
unsigned char c = s[i];
if (c == '=' // Note- special case for fuse paths...
|| c == '&' // Note- special case for s3...
|| c == '%'
|| c == '.'
|| c == '-'
|| c == '_'
|| c == '~'
|| (c >= 'a' && c <= 'z')
|| (c >= 'A' && c <= 'Z')
|| (c >= '0' && c <= '9'))
{
result += c;
}else{
result += "%";
result += s3fs_hex_upper(&c, 1);
}
}
return result;
}
std::string urlDecode(const std::string& s)
{
std::string result;
for(size_t i = 0; i < s.length(); ++i){
if(s[i] != '%'){
result += s[i];
}else{
int ch = 0;
if(s.length() <= ++i){
break; // wrong format.
}
ch += ('0' <= s[i] && s[i] <= '9') ? (s[i] - '0') : ('A' <= s[i] && s[i] <= 'F') ? (s[i] - 'A' + 0x0a) : ('a' <= s[i] && s[i] <= 'f') ? (s[i] - 'a' + 0x0a) : 0x00;
if(s.length() <= ++i){
break; // wrong format.
}
ch *= 16;
ch += ('0' <= s[i] && s[i] <= '9') ? (s[i] - '0') : ('A' <= s[i] && s[i] <= 'F') ? (s[i] - 'A' + 0x0a) : ('a' <= s[i] && s[i] <= 'f') ? (s[i] - 'a' + 0x0a) : 0x00;
result += static_cast<char>(ch);
}
}
return result;
}
bool takeout_str_dquart(std::string& str)
{
size_t pos;
// '"' for start
if(std::string::npos != (pos = str.find_first_of('\"'))){
str.erase(0, pos + 1);
// '"' for end
if(std::string::npos == (pos = str.find_last_of('\"'))){
return false;
}
str.erase(pos);
if(std::string::npos != str.find_first_of('\"')){
return false;
}
}
return true;
}
//
// ex. target="http://......?keyword=value&..."
//
bool get_keyword_value(string& target, const char* keyword, string& value)
bool get_keyword_value(const std::string& target, const char* keyword, std::string& value)
{
if(!keyword){
return false;
}
size_t spos;
size_t epos;
if(string::npos == (spos = target.find(keyword))){
return false;
}
spos += strlen(keyword);
if('=' != target.at(spos)){
return false;
}
spos++;
if(string::npos == (epos = target.find('&', spos))){
value = target.substr(spos);
}else{
value = target.substr(spos, (epos - spos));
}
return true;
}
string prepare_url(const char* url)
{
FPRNINFO("URL is %s", url);
string uri;
string host;
string path;
string url_str = str(url);
string token = str("/" + bucket);
int bucket_pos = url_str.find(token);
int bucket_length = token.size();
int uri_length = 7;
if(!strncasecmp(url_str.c_str(), "https://", 8)){
uri_length = 8;
}
uri = url_str.substr(0, uri_length);
if(!pathrequeststyle){
host = bucket + "." + url_str.substr(uri_length, bucket_pos - uri_length).c_str();
path = url_str.substr((bucket_pos + bucket_length));
}else{
host = url_str.substr(uri_length, bucket_pos - uri_length).c_str();
string part = url_str.substr((bucket_pos + bucket_length));
if('/' != part[0]){
part = "/" + part;
if(!keyword){
return false;
}
path = "/" + bucket + part;
}
url_str = uri + host + path;
FPRNINFO("URL changed is %s", url_str.c_str());
return str(url_str);
size_t spos;
size_t epos;
if(std::string::npos == (spos = target.find(keyword))){
return false;
}
spos += strlen(keyword);
if('=' != target[spos]){
return false;
}
spos++;
if(std::string::npos == (epos = target.find('&', spos))){
value = target.substr(spos);
}else{
value = target.substr(spos, (epos - spos));
}
return true;
}
/**
* Returns the current date
* in a format suitable for a HTTP request header.
*/
string get_date()
//
// Returns the current date
// in a format suitable for a HTTP request header.
//
std::string get_date_rfc850()
{
char buf[100];
time_t t = time(NULL);
strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&t));
return buf;
char buf[100];
time_t t = time(NULL);
struct tm res;
strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S GMT", gmtime_r(&t, &res));
return buf;
}
void get_date_sigv3(std::string& date, std::string& date8601)
{
time_t tm = time(NULL);
date = get_date_string(tm);
date8601 = get_date_iso8601(tm);
}
std::string get_date_string(time_t tm)
{
char buf[100];
struct tm res;
strftime(buf, sizeof(buf), "%Y%m%d", gmtime_r(&tm, &res));
return buf;
}
std::string get_date_iso8601(time_t tm)
{
char buf[100];
struct tm res;
strftime(buf, sizeof(buf), "%Y%m%dT%H%M%SZ", gmtime_r(&tm, &res));
return buf;
}
bool get_unixtime_from_iso8601(const char* pdate, time_t& unixtime)
{
if(!pdate){
return false;
}
struct tm tm;
char* prest = strptime(pdate, "%Y-%m-%dT%T", &tm);
if(prest == pdate){
// wrong format
return false;
}
unixtime = mktime(&tm);
return true;
}
//
// Convert to unixtime from std::string which formatted by following:
// "12Y12M12D12h12m12s", "86400s", "9h30m", etc
//
bool convert_unixtime_from_option_arg(const char* argv, time_t& unixtime)
{
if(!argv){
return false;
}
unixtime = 0;
const char* ptmp;
int last_unit_type = 0; // unit flag.
bool is_last_number;
time_t tmptime;
for(ptmp = argv, is_last_number = true, tmptime = 0; ptmp && *ptmp; ++ptmp){
if('0' <= *ptmp && *ptmp <= '9'){
tmptime *= 10;
tmptime += static_cast<time_t>(*ptmp - '0');
is_last_number = true;
}else if(is_last_number){
if('Y' == *ptmp && 1 > last_unit_type){
unixtime += (tmptime * (60 * 60 * 24 * 365)); // average 365 day / year
last_unit_type = 1;
}else if('M' == *ptmp && 2 > last_unit_type){
unixtime += (tmptime * (60 * 60 * 24 * 30)); // average 30 day / month
last_unit_type = 2;
}else if('D' == *ptmp && 3 > last_unit_type){
unixtime += (tmptime * (60 * 60 * 24));
last_unit_type = 3;
}else if('h' == *ptmp && 4 > last_unit_type){
unixtime += (tmptime * (60 * 60));
last_unit_type = 4;
}else if('m' == *ptmp && 5 > last_unit_type){
unixtime += (tmptime * 60);
last_unit_type = 5;
}else if('s' == *ptmp && 6 > last_unit_type){
unixtime += tmptime;
last_unit_type = 6;
}else{
return false;
}
tmptime = 0;
is_last_number = false;
}else{
return false;
}
}
if(is_last_number){
return false;
}
return true;
}
static std::string s3fs_hex(const unsigned char* input, size_t length, const char *hexAlphabet)
{
std::string hex;
for(size_t pos = 0; pos < length; ++pos){
hex += hexAlphabet[input[pos] / 16];
hex += hexAlphabet[input[pos] % 16];
}
return hex;
}
std::string s3fs_hex_lower(const unsigned char* input, size_t length)
{
return s3fs_hex(input, length, "0123456789abcdef");
}
std::string s3fs_hex_upper(const unsigned char* input, size_t length)
{
return s3fs_hex(input, length, "0123456789ABCDEF");
}
char* s3fs_base64(const unsigned char* input, size_t length)
{
static const char base[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
char* result;
if(!input || 0 == length){
return NULL;
}
result = new char[((length / 3) + 1) * 4 + 1];
unsigned char parts[4];
size_t rpos;
size_t wpos;
for(rpos = 0, wpos = 0; rpos < length; rpos += 3){
parts[0] = (input[rpos] & 0xfc) >> 2;
parts[1] = ((input[rpos] & 0x03) << 4) | ((((rpos + 1) < length ? input[rpos + 1] : 0x00) & 0xf0) >> 4);
parts[2] = (rpos + 1) < length ? (((input[rpos + 1] & 0x0f) << 2) | ((((rpos + 2) < length ? input[rpos + 2] : 0x00) & 0xc0) >> 6)) : 0x40;
parts[3] = (rpos + 2) < length ? (input[rpos + 2] & 0x3f) : 0x40;
result[wpos++] = base[parts[0]];
result[wpos++] = base[parts[1]];
result[wpos++] = base[parts[2]];
result[wpos++] = base[parts[3]];
}
result[wpos] = '\0';
return result;
}
inline unsigned char char_decode64(const char ch)
{
unsigned char by;
if('A' <= ch && ch <= 'Z'){ // A - Z
by = static_cast<unsigned char>(ch - 'A');
}else if('a' <= ch && ch <= 'z'){ // a - z
by = static_cast<unsigned char>(ch - 'a' + 26);
}else if('0' <= ch && ch <= '9'){ // 0 - 9
by = static_cast<unsigned char>(ch - '0' + 52);
}else if('+' == ch){ // +
by = 62;
}else if('/' == ch){ // /
by = 63;
}else if('=' == ch){ // =
by = 64;
}else{ // something wrong
by = UCHAR_MAX;
}
return by;
}
unsigned char* s3fs_decode64(const char* input, size_t* plength)
{
unsigned char* result;
if(!input || 0 == strlen(input) || !plength){
return NULL;
}
result = new unsigned char[strlen(input) + 1];
unsigned char parts[4];
size_t input_len = strlen(input);
size_t rpos;
size_t wpos;
for(rpos = 0, wpos = 0; rpos < input_len; rpos += 4){
parts[0] = char_decode64(input[rpos]);
parts[1] = (rpos + 1) < input_len ? char_decode64(input[rpos + 1]) : 64;
parts[2] = (rpos + 2) < input_len ? char_decode64(input[rpos + 2]) : 64;
parts[3] = (rpos + 3) < input_len ? char_decode64(input[rpos + 3]) : 64;
result[wpos++] = ((parts[0] << 2) & 0xfc) | ((parts[1] >> 4) & 0x03);
if(64 == parts[2]){
break;
}
result[wpos++] = ((parts[1] << 4) & 0xf0) | ((parts[2] >> 2) & 0x0f);
if(64 == parts[3]){
break;
}
result[wpos++] = ((parts[2] << 6) & 0xc0) | (parts[3] & 0x3f);
}
result[wpos] = '\0';
*plength = wpos;
return result;
}
//
// detect and rewrite invalid utf8. We take invalid bytes
// and encode them into a private region of the unicode
// space. This is sometimes known as wtf8, wobbly transformation format.
// it is necessary because S3 validates the utf8 used for identifiers for
// correctness, while some clients may provide invalid utf, notably
// windows using cp1252.
//
// Base location for transform. The range 0xE000 - 0xF8ff
// is a private range, se use the start of this range.
static const unsigned int escape_base = 0xe000;
// encode bytes into wobbly utf8.
// 'result' can be null. returns true if transform was needed.
bool s3fs_wtf8_encode(const char *s, std::string *result)
{
bool invalid = false;
// Pass valid utf8 code through
for (; *s; s++) {
const unsigned char c = *s;
// single byte encoding
if (c <= 0x7f) {
if (result) {
*result += c;
}
continue;
}
// otherwise, it must be one of the valid start bytes
if ( c >= 0xc2 && c <= 0xf5 ) {
// two byte encoding
// don't need bounds check, std::string is zero terminated
if ((c & 0xe0) == 0xc0 && (s[1] & 0xc0) == 0x80) {
// all two byte encodings starting higher than c1 are valid
if (result) {
*result += c;
*result += *(++s);
}
continue;
}
// three byte encoding
if ((c & 0xf0) == 0xe0 && (s[1] & 0xc0) == 0x80 && (s[2] & 0xc0) == 0x80) {
const unsigned code = ((c & 0x0f) << 12) | ((s[1] & 0x3f) << 6) | (s[2] & 0x3f);
if (code >= 0x800 && ! (code >= 0xd800 && code <= 0xd8ff)) {
// not overlong and not a surrogate pair
if (result) {
*result += c;
*result += *(++s);
*result += *(++s);
}
continue;
}
}
// four byte encoding
if ((c & 0xf8) == 0xf0 && (s[1] & 0xc0) == 0x80 && (s[2] & 0xc0) == 0x80 && (s[3] & 0xc0) == 0x80) {
const unsigned code = ((c & 0x07) << 18) | ((s[1] & 0x3f) << 12) | ((s[2] & 0x3f) << 6) | (s[3] & 0x3f);
if (code >= 0x10000 && code <= 0x10ffff) {
// not overlong and in defined unicode space
if (result) {
*result += c;
*result += *(++s);
*result += *(++s);
*result += *(++s);
}
continue;
}
}
}
// printf("invalid %02x at %d\n", c, i);
// Invalid utf8 code. Convert it to a private two byte area of unicode
// e.g. the e000 - f8ff area. This will be a three byte encoding
invalid = true;
if (result) {
unsigned escape = escape_base + c;
*result += static_cast<char>(0xe0 | ((escape >> 12) & 0x0f));
*result += static_cast<char>(0x80 | ((escape >> 06) & 0x3f));
*result += static_cast<char>(0x80 | ((escape >> 00) & 0x3f));
}
}
return invalid;
}
std::string s3fs_wtf8_encode(const std::string &s)
{
std::string result;
s3fs_wtf8_encode(s.c_str(), &result);
return result;
}
// The reverse operation, turn encoded bytes back into their original values
// The code assumes that we map to a three-byte code point.
bool s3fs_wtf8_decode(const char *s, std::string *result)
{
bool encoded = false;
for (; *s; s++) {
unsigned char c = *s;
// look for a three byte tuple matching our encoding code
if ((c & 0xf0) == 0xe0 && (s[1] & 0xc0) == 0x80 && (s[2] & 0xc0) == 0x80) {
unsigned code = (c & 0x0f) << 12;
code |= (s[1] & 0x3f) << 6;
code |= (s[2] & 0x3f) << 0;
if (code >= escape_base && code <= escape_base + 0xff) {
// convert back
encoded = true;
if(result){
*result += static_cast<char>(code - escape_base);
}
s+=2;
continue;
}
}
if (result) {
*result += c;
}
}
return encoded;
}
std::string s3fs_wtf8_decode(const std::string &s)
{
std::string result;
s3fs_wtf8_decode(s.c_str(), &result);
return result;
}
/*
@ -223,6 +598,6 @@ string get_date()
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
* vim600: expandtab sw=4 ts=4 fdm=marker
* vim<600: expandtab sw=4 ts=4
*/

View File

@ -1,7 +1,7 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright 2007-2008 Randy Rizun <rrizun@gmail.com>
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,38 +17,97 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef S3FS_STRING_UTIL_H_
#define S3FS_STRING_UTIL_H_
/*
* A collection of string utilities for manipulating URLs and HTTP responses.
*/
#include <string.h>
#include <syslog.h>
//
// A collection of string utilities for manipulating URLs and HTTP responses.
//
//-------------------------------------------------------------------
// Global variables
//-------------------------------------------------------------------
extern const char SPACES[];
#include <string>
#include <sstream>
//-------------------------------------------------------------------
// Inline functions
//-------------------------------------------------------------------
static inline int is_prefix(const char *str, const char *prefix) { return strncmp(str, prefix, strlen(prefix)) == 0; }
static inline const char* SAFESTRPTR(const char *strptr) { return strptr ? strptr : ""; }
#define SPACES " \t\r\n"
#define STR2NCMP(str1, str2) strncmp(str1, str2, strlen(str2))
//-------------------------------------------------------------------
// Templates
//-------------------------------------------------------------------
template <class T> std::string str(T value);
template<typename T> std::string str(T value) {
std::stringstream s;
s << value;
return s.str();
}
//-------------------------------------------------------------------
// Macros(WTF8)
//-------------------------------------------------------------------
#define WTF8_ENCODE(ARG) \
std::string ARG##_buf; \
const char * ARG = _##ARG; \
if (use_wtf8 && s3fs_wtf8_encode( _##ARG, 0 )) { \
s3fs_wtf8_encode( _##ARG, &ARG##_buf); \
ARG = ARG##_buf.c_str(); \
}
off_t s3fs_strtoofft(const char* str, bool is_base_16 = false);
//-------------------------------------------------------------------
// Utilities
//-------------------------------------------------------------------
//
// Convert string to off_t. Returns false on bad input.
// Replacement for C++11 std::stoll.
//
bool s3fs_strtoofft(off_t* value, const char* str, int base = 0);
//
// This function returns 0 if a value that cannot be converted is specified.
// Only call if 0 is considered an error and the operation can continue.
//
off_t cvt_strtoofft(const char* str, int base);
std::string trim_left(const std::string &s, const std::string &t = SPACES);
std::string trim_right(const std::string &s, const std::string &t = SPACES);
std::string trim(const std::string &s, const std::string &t = SPACES);
//
// String Manipulation
//
std::string trim_left(const std::string &s, const char *t = SPACES);
std::string trim_right(const std::string &s, const char *t = SPACES);
std::string trim(const std::string &s, const char *t = SPACES);
std::string lower(std::string s);
std::string IntToStr(int);
std::string get_date();
//
// Date string
//
std::string get_date_rfc850();
void get_date_sigv3(std::string& date, std::string& date8601);
std::string get_date_string(time_t tm);
std::string get_date_iso8601(time_t tm);
bool get_unixtime_from_iso8601(const char* pdate, time_t& unixtime);
bool convert_unixtime_from_option_arg(const char* argv, time_t& unixtime);
//
// For encoding
//
std::string urlEncode(const std::string &s);
std::string prepare_url(const char* url);
bool get_keyword_value(std::string& target, const char* keyword, std::string& value);
std::string urlEncode2(const std::string &s);
std::string urlDecode(const std::string& s);
bool takeout_str_dquart(std::string& str);
bool get_keyword_value(const std::string& target, const char* keyword, std::string& value);
//
// For binary string
//
std::string s3fs_hex_lower(const unsigned char* input, size_t length);
std::string s3fs_hex_upper(const unsigned char* input, size_t length);
char* s3fs_base64(const unsigned char* input, size_t length);
unsigned char* s3fs_decode64(const char* input, size_t* plength);
//
// WTF8
//
bool s3fs_wtf8_encode(const char *s, std::string *result);
std::string s3fs_wtf8_encode(const std::string &s);
bool s3fs_wtf8_decode(const char *s, std::string *result);
std::string s3fs_wtf8_decode(const std::string &s);
#endif // S3FS_STRING_UTIL_H_
@ -57,6 +116,6 @@ bool get_keyword_value(std::string& target, const char* keyword, std::string& va
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
* vim600: expandtab sw=4 ts=4 fdm=marker
* vim<600: expandtab sw=4 ts=4
*/

93
src/test_curl_util.cpp Normal file
View File

@ -0,0 +1,93 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2020 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 <string>
#include <cstring>
#include "curl_util.h"
#include "test_util.h"
#define ASSERT_IS_SORTED(x) assert_is_sorted((x), __FILE__, __LINE__)
void assert_is_sorted(struct curl_slist* list, const char *file, int line)
{
for(; list != NULL; list = list->next){
std::string key1 = list->data;
key1.erase(key1.find(':'));
std::string key2 = list->data;
key2.erase(key2.find(':'));
std::cerr << "key1: " << key1 << " key2: " << key2 << std::endl;
if(strcasecmp(key1.c_str(), key2.c_str()) > 0){
std::cerr << "not sorted: " << key1 << " " << key2 << " at " << file << ":" << line << std::endl;
std::exit(1);
}
}
std::cerr << std::endl;
}
size_t curl_slist_length(const struct curl_slist* list)
{
size_t len = 0;
for(; list != NULL; list = list->next){
++len;
}
return len;
}
void test_sort_insert()
{
struct curl_slist* list = NULL;
ASSERT_IS_SORTED(list);
// add to head
list = curl_slist_sort_insert(list, "2", "val");
ASSERT_IS_SORTED(list);
// add to tail
list = curl_slist_sort_insert(list, "4", "val");
ASSERT_IS_SORTED(list);
// add in between
list = curl_slist_sort_insert(list, "3", "val");
ASSERT_IS_SORTED(list);
// add to head
list = curl_slist_sort_insert(list, "1", "val");
ASSERT_IS_SORTED(list);
ASSERT_STREQUALS("1: val", list->data);
// replace head
list = curl_slist_sort_insert(list, "1", "val2");
ASSERT_IS_SORTED(list);
ASSERT_EQUALS(static_cast<size_t>(4), curl_slist_length(list));
ASSERT_STREQUALS("1: val2", list->data);
curl_slist_free_all(list);
}
int main(int argc, char *argv[])
{
test_sort_insert();
return 0;
}
/*
* 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
*/

82
src/test_page_list.cpp Normal file
View File

@ -0,0 +1,82 @@
/*
* 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 <limits>
#include <stdint.h>
#include <string>
#include "fdcache.h"
#include "test_util.h"
bool CacheFileStat::Open() { return false; }
void test_compress()
{
PageList list;
ASSERT_EQUALS(off_t(0), list.Size());
list.Init(42, /*is_loaded=*/ false, /*is_modified=*/ false);
ASSERT_EQUALS(off_t(42), list.Size());
ASSERT_FALSE(list.IsPageLoaded(0, 1));
list.SetPageLoadedStatus(0, 1, /*pstatus=*/ PageList::PAGE_LOADED);
ASSERT_TRUE(list.IsPageLoaded(0, 1));
ASSERT_FALSE(list.IsPageLoaded(0, 2));
off_t start = 0;
off_t size = 0;
ASSERT_TRUE(list.FindUnloadedPage(0, start, size));
ASSERT_EQUALS(off_t(1), start);
ASSERT_EQUALS(off_t(41), size);
// test adding subsequent page then compressing
list.SetPageLoadedStatus(1, 3, /*pstatus=*/ PageList::PAGE_LOADED);
list.Compress();
ASSERT_TRUE(list.IsPageLoaded(0, 3));
ASSERT_TRUE(list.FindUnloadedPage(0, start, size));
ASSERT_EQUALS(off_t(4), start);
ASSERT_EQUALS(off_t(38), size);
// test adding non-contiguous page then compressing
list.SetPageLoadedStatus(5, 1, /*pstatus=*/ PageList::PAGE_LOADED);
list.Compress();
ASSERT_TRUE(list.FindUnloadedPage(0, start, size));
ASSERT_EQUALS(off_t(4), start);
ASSERT_EQUALS(off_t(1), size);
list.Dump();
printf("\n");
// test adding page between two pages then compressing
list.SetPageLoadedStatus(4, 1, /*pstatus=*/ PageList::PAGE_LOADED);
list.Compress();
list.Dump();
ASSERT_TRUE(list.FindUnloadedPage(0, start, size));
ASSERT_EQUALS(off_t(6), start);
ASSERT_EQUALS(off_t(36), size);
}
int main(int argc, char *argv[])
{
test_compress();
return 0;
}

160
src/test_string_util.cpp Normal file
View File

@ -0,0 +1,160 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2014 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 <cstdlib>
#include <limits>
#include <stdint.h>
#include <strings.h>
#include <string>
#include <map>
#include "common.h"
#include "s3fs.h"
#include "string_util.h"
#include "test_util.h"
//-------------------------------------------------------------------
// Global variables for test_string_util
//-------------------------------------------------------------------
bool foreground = false;
std::string instance_name;
void test_trim()
{
ASSERT_EQUALS(std::string("1234"), trim(" 1234 "));
ASSERT_EQUALS(std::string("1234"), trim("1234 "));
ASSERT_EQUALS(std::string("1234"), trim(" 1234"));
ASSERT_EQUALS(std::string("1234"), trim("1234"));
ASSERT_EQUALS(std::string("1234 "), trim_left(" 1234 "));
ASSERT_EQUALS(std::string("1234 "), trim_left("1234 "));
ASSERT_EQUALS(std::string("1234"), trim_left(" 1234"));
ASSERT_EQUALS(std::string("1234"), trim_left("1234"));
ASSERT_EQUALS(std::string(" 1234"), trim_right(" 1234 "));
ASSERT_EQUALS(std::string("1234"), trim_right("1234 "));
ASSERT_EQUALS(std::string(" 1234"), trim_right(" 1234"));
ASSERT_EQUALS(std::string("1234"), trim_right("1234"));
ASSERT_EQUALS(std::string("0"), str(0));
ASSERT_EQUALS(std::string("1"), str(1));
ASSERT_EQUALS(std::string("-1"), str(-1));
ASSERT_EQUALS(std::string("9223372036854775807"), str(std::numeric_limits<int64_t>::max()));
ASSERT_EQUALS(std::string("-9223372036854775808"), str(std::numeric_limits<int64_t>::min()));
ASSERT_EQUALS(std::string("0"), str(std::numeric_limits<uint64_t>::min()));
ASSERT_EQUALS(std::string("18446744073709551615"), str(std::numeric_limits<uint64_t>::max()));
}
void test_base64()
{
size_t len;
ASSERT_STREQUALS(s3fs_base64(NULL, 0), NULL);
ASSERT_STREQUALS(reinterpret_cast<const char *>(s3fs_decode64(NULL, &len)), NULL);
ASSERT_STREQUALS(s3fs_base64(reinterpret_cast<const unsigned char *>(""), 0), NULL);
ASSERT_STREQUALS(reinterpret_cast<const char *>(s3fs_decode64("", &len)), NULL);
ASSERT_STREQUALS(s3fs_base64(reinterpret_cast<const unsigned char *>("1"), 1), "MQ==");
ASSERT_STREQUALS(reinterpret_cast<const char *>(s3fs_decode64("MQ==", &len)), "1");
ASSERT_EQUALS(len, static_cast<size_t>(1));
ASSERT_STREQUALS(s3fs_base64(reinterpret_cast<const unsigned char *>("12"), 2), "MTI=");
ASSERT_STREQUALS(reinterpret_cast<const char *>(s3fs_decode64("MTI=", &len)), "12");
ASSERT_EQUALS(len, static_cast<size_t>(2));
ASSERT_STREQUALS(s3fs_base64(reinterpret_cast<const unsigned char *>("123"), 3), "MTIz");
ASSERT_STREQUALS(reinterpret_cast<const char *>(s3fs_decode64("MTIz", &len)), "123");
ASSERT_EQUALS(len, static_cast<size_t>(3));
ASSERT_STREQUALS(s3fs_base64(reinterpret_cast<const unsigned char *>("1234"), 4), "MTIzNA==");
ASSERT_STREQUALS(reinterpret_cast<const char *>(s3fs_decode64("MTIzNA==", &len)), "1234");
ASSERT_EQUALS(len, static_cast<size_t>(4));
// TODO: invalid input
}
void test_strtoofft()
{
off_t value;
ASSERT_TRUE(s3fs_strtoofft(&value, "0"));
ASSERT_EQUALS(value, static_cast<off_t>(0L));
ASSERT_TRUE(s3fs_strtoofft(&value, "9"));
ASSERT_EQUALS(value, static_cast<off_t>(9L));
ASSERT_FALSE(s3fs_strtoofft(&value, "A"));
ASSERT_TRUE(s3fs_strtoofft(&value, "A", /*base=*/ 16));
ASSERT_EQUALS(value, static_cast<off_t>(10L));
ASSERT_TRUE(s3fs_strtoofft(&value, "F", /*base=*/ 16));
ASSERT_EQUALS(value, static_cast<off_t>(15L));
ASSERT_TRUE(s3fs_strtoofft(&value, "a", /*base=*/ 16));
ASSERT_EQUALS(value, static_cast<off_t>(10L));
ASSERT_TRUE(s3fs_strtoofft(&value, "f", /*base=*/ 16));
ASSERT_EQUALS(value, static_cast<off_t>(15L));
ASSERT_TRUE(s3fs_strtoofft(&value, "deadbeef", /*base=*/ 16));
ASSERT_EQUALS(value, static_cast<off_t>(3735928559L));
}
void test_wtf8_encoding()
{
std::string ascii("normal std::string");
std::string utf8("Hyld\xc3\xbdpi \xc3\xbej\xc3\xb3\xc3\xb0""f\xc3\xa9lagsins vex \xc3\xbar k\xc3\xa6rkomnu b\xc3\xb6li \xc3\xad \xc3\xa1st");
std::string cp1252("Hyld\xfdpi \xfej\xf3\xf0""f\xe9lagsins vex \xfar k\xe6rkomnu b\xf6li \xed \xe1st");
std::string broken = utf8;
broken[14] = 0x97;
std::string mixed = ascii + utf8 + cp1252;
ASSERT_EQUALS(s3fs_wtf8_encode(ascii), ascii);
ASSERT_EQUALS(s3fs_wtf8_decode(ascii), ascii);
ASSERT_EQUALS(s3fs_wtf8_encode(utf8), utf8);
ASSERT_EQUALS(s3fs_wtf8_decode(utf8), utf8);
ASSERT_NEQUALS(s3fs_wtf8_encode(cp1252), cp1252);
ASSERT_EQUALS(s3fs_wtf8_decode(s3fs_wtf8_encode(cp1252)), cp1252);
ASSERT_NEQUALS(s3fs_wtf8_encode(broken), broken);
ASSERT_EQUALS(s3fs_wtf8_decode(s3fs_wtf8_encode(broken)), broken);
ASSERT_NEQUALS(s3fs_wtf8_encode(mixed), mixed);
ASSERT_EQUALS(s3fs_wtf8_decode(s3fs_wtf8_encode(mixed)), mixed);
}
int main(int argc, char *argv[])
{
S3fsLog singletonLog;
test_trim();
test_base64();
test_strtoofft();
test_wtf8_encoding();
return 0;
}
/*
* 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
*/

94
src/test_util.h Normal file
View File

@ -0,0 +1,94 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2014 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.
*/
#ifndef S3FS_TEST_UTIL_H_
#define S3FS_TEST_UTIL_H_
#include <cstdlib>
#include <iostream>
#include <stdio.h>
#include "string_util.h"
template <typename T> void assert_equals(const T &x, const T &y, const char *file, int line)
{
if (x != y) {
std::cerr << x << " != " << y << " at " << file << ":" << line << std::endl;
std::cerr << std::endl;
std::exit(1);
}
}
template <> void assert_equals(const std::string &x, const std::string &y, const char *file, int line)
{
if (x != y) {
std::cerr << x << " != " << y << " at " << file << ":" << line << std::endl;
std::cerr << s3fs_hex_lower(reinterpret_cast<const unsigned char *>(x.c_str()), x.size()) << std::endl;
std::cerr << s3fs_hex_lower(reinterpret_cast<const unsigned char *>(y.c_str()), y.size()) << std::endl;
std::exit(1);
}
}
template <typename T> void assert_nequals(const T &x, const T &y, const char *file, int line)
{
if (x == y) {
std::cerr << x << " == " << y << " at " << file << ":" << line << std::endl;
std::exit(1);
}
}
template <> void assert_nequals(const std::string &x, const std::string &y, const char *file, int line)
{
if (x == y) {
std::cerr << x << " == " << y << " at " << file << ":" << line << std::endl;
std::cerr << s3fs_hex_lower(reinterpret_cast<const unsigned char *>(x.c_str()), x.size()) << std::endl;
std::cerr << s3fs_hex_lower(reinterpret_cast<const unsigned char *>(y.c_str()), y.size()) << std::endl;
std::exit(1);
}
}
void assert_strequals(const char *x, const char *y, const char *file, int line)
{
if(x == NULL && y == NULL){
return;
// cppcheck-suppress nullPointerRedundantCheck
} else if(x == NULL || y == NULL || strcmp(x, y) != 0){
std::cerr << (x ? x : "null") << " != " << (y ? y : "null") << " at " << file << ":" << line << std::endl;
std::exit(1);
}
}
#define ASSERT_TRUE(x) assert_equals((x), true, __FILE__, __LINE__)
#define ASSERT_FALSE(x) assert_equals((x), false, __FILE__, __LINE__)
#define ASSERT_EQUALS(x, y) assert_equals((x), (y), __FILE__, __LINE__)
#define ASSERT_NEQUALS(x, y) assert_nequals((x), (y), __FILE__, __LINE__)
#define ASSERT_STREQUALS(x, y) assert_strequals((x), (y), __FILE__, __LINE__)
#endif // S3FS_TEST_UTIL_H_
/*
* 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
*/

305
src/types.h Normal file
View File

@ -0,0 +1,305 @@
/*
* s3fs - FUSE-based file system backed by Amazon S3
*
* Copyright(C) 2007 Randy Rizun <rrizun@gmail.com>
*
* 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.
*/
#ifndef S3FS_TYPES_H_
#define S3FS_TYPES_H_
#include <cstdlib>
#include <cstring>
#include <string>
#include <map>
#include <list>
#include <vector>
//
// For extended attribute
// (HAVE_XXX symbols are defined in config.h)
//
#ifdef HAVE_SYS_EXTATTR_H
#include <sys/extattr.h>
#elif HAVE_ATTR_XATTR_H
#include <attr/xattr.h>
#elif HAVE_SYS_XATTR_H
#include <sys/xattr.h>
#endif
#if __cplusplus < 201103L
#define OPERATOR_EXPLICIT
#else
#define OPERATOR_EXPLICIT explicit
#endif
//-------------------------------------------------------------------
// xattrs_t
//-------------------------------------------------------------------
//
// Header "x-amz-meta-xattr" is for extended attributes.
// This header is url encoded string which is json formatted.
// x-amz-meta-xattr:urlencode({"xattr-1":"base64(value-1)","xattr-2":"base64(value-2)","xattr-3":"base64(value-3)"})
//
typedef struct xattr_value
{
unsigned char* pvalue;
size_t length;
explicit xattr_value(unsigned char* pval = NULL, size_t len = 0) : pvalue(pval), length(len) {}
~xattr_value()
{
delete[] pvalue;
}
}XATTRVAL, *PXATTRVAL;
typedef std::map<std::string, PXATTRVAL> xattrs_t;
//-------------------------------------------------------------------
// acl_t
//-------------------------------------------------------------------
class acl_t{
public:
enum Value{
PRIVATE,
PUBLIC_READ,
PUBLIC_READ_WRITE,
AWS_EXEC_READ,
AUTHENTICATED_READ,
BUCKET_OWNER_READ,
BUCKET_OWNER_FULL_CONTROL,
LOG_DELIVERY_WRITE,
UNKNOWN
};
// cppcheck-suppress noExplicitConstructor
acl_t(Value value) : value_(value) {}
operator Value() const { return value_; }
const char* str() const
{
switch(value_){
case PRIVATE:
return "private";
case PUBLIC_READ:
return "public-read";
case PUBLIC_READ_WRITE:
return "public-read-write";
case AWS_EXEC_READ:
return "aws-exec-read";
case AUTHENTICATED_READ:
return "authenticated-read";
case BUCKET_OWNER_READ:
return "bucket-owner-read";
case BUCKET_OWNER_FULL_CONTROL:
return "bucket-owner-full-control";
case LOG_DELIVERY_WRITE:
return "log-delivery-write";
case UNKNOWN:
return NULL;
}
abort();
}
static acl_t from_str(const char *acl)
{
if(0 == strcmp(acl, "private")){
return PRIVATE;
}else if(0 == strcmp(acl, "public-read")){
return PUBLIC_READ;
}else if(0 == strcmp(acl, "public-read-write")){
return PUBLIC_READ_WRITE;
}else if(0 == strcmp(acl, "aws-exec-read")){
return AWS_EXEC_READ;
}else if(0 == strcmp(acl, "authenticated-read")){
return AUTHENTICATED_READ;
}else if(0 == strcmp(acl, "bucket-owner-read")){
return BUCKET_OWNER_READ;
}else if(0 == strcmp(acl, "bucket-owner-full-control")){
return BUCKET_OWNER_FULL_CONTROL;
}else if(0 == strcmp(acl, "log-delivery-write")){
return LOG_DELIVERY_WRITE;
}else{
return UNKNOWN;
}
}
private:
OPERATOR_EXPLICIT operator bool();
Value value_;
};
//-------------------------------------------------------------------
// sse_type_t
//-------------------------------------------------------------------
class sse_type_t{
public:
enum Value{
SSE_DISABLE = 0, // not use server side encrypting
SSE_S3, // server side encrypting by S3 key
SSE_C, // server side encrypting by custom key
SSE_KMS // server side encrypting by kms id
};
// cppcheck-suppress noExplicitConstructor
sse_type_t(Value value) : value_(value) {}
operator Value() const { return value_; }
private:
//OPERATOR_EXPLICIT operator bool();
Value value_;
};
enum signature_type_t {
V2_ONLY,
V4_ONLY,
V2_OR_V4
};
//----------------------------------------------
// etaglist_t / filepart / untreatedpart
//----------------------------------------------
typedef std::list<std::string> etaglist_t;
//
// Each part information for Multipart upload
//
struct filepart
{
bool uploaded; // does finish uploading
std::string etag; // expected etag value
int fd; // base file(temporary full file) descriptor
off_t startpos; // seek fd point for uploading
off_t size; // uploading size
bool is_copy; // whether is copy multipart
std::string* petag; // use only parallel upload
filepart(bool is_uploaded = false, int _fd = -1, off_t part_start = 0, off_t part_size = -1, bool is_copy_part = false, std::string* petag = NULL) : uploaded(false), fd(_fd), startpos(part_start), size(part_size), is_copy(is_copy_part), petag(petag) {}
~filepart()
{
clear();
}
void clear()
{
uploaded = false;
etag = "";
fd = -1;
startpos = 0;
size = -1;
is_copy = false;
petag = NULL;
}
void add_etag_list(etaglist_t* list)
{
list->push_back(std::string());
petag = &list->back();
}
void add_etag(std::string* petagobj)
{
petag = petagobj;
}
};
typedef std::list<filepart> filepart_list_t;
//
// Each part information for Untreated parts
//
struct untreatedpart
{
off_t start; // untreated start position
off_t size; // number of untreated bytes
long untreated_tag; // untreated part tag
untreatedpart(off_t part_start = 0, off_t part_size = 0, long part_untreated_tag = 0) : start(part_start), size(part_size), untreated_tag(part_untreated_tag)
{
if(part_start < 0 || part_size <= 0){
clear(); // wrong parameter, so clear value.
}
}
~untreatedpart()
{
clear();
}
void clear()
{
start = 0;
size = 0;
untreated_tag = 0;
}
bool check_overlap(off_t chk_start, off_t chk_size)
{
if(chk_start < 0 || chk_size <= 0 || (chk_start + chk_size) < start || (start + size) < chk_start){
return false;
}
return true;
}
bool stretch(off_t add_start, off_t add_size, long tag)
{
if(!check_overlap(add_start, add_size)){
return false;
}
off_t new_start = std::min(start, add_start);
off_t new_next_start = std::max((start + size), (add_start + add_size));
start = new_start;
size = new_next_start - new_start;
untreated_tag = tag;
return true;
}
};
typedef std::list<untreatedpart> untreated_list_t;
//-------------------------------------------------------------------
// mimes_t
//-------------------------------------------------------------------
struct case_insensitive_compare_func
{
bool operator()(const std::string& a, const std::string& b) const {
return strcasecmp(a.c_str(), b.c_str()) < 0;
}
};
typedef std::map<std::string, std::string, case_insensitive_compare_func> mimes_t;
//-------------------------------------------------------------------
// Typedefs specialized for use
//-------------------------------------------------------------------
typedef std::list<std::string> readline_t;
typedef std::map<std::string, std::string> kvmap_t;
typedef std::map<std::string, kvmap_t> bucketkvmap_t;
#endif // S3FS_TYPES_H_
/*
* 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
*/

View File

@ -17,13 +17,24 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
######################################################################
TESTS=small-integration-test.sh
EXTRA_DIST = \
integration-test-common.sh \
require-root.sh \
small-integration-test.sh \
mergedir.sh \
sample_delcache.sh \
sample_ahbe.conf
integration-test-common.sh \
require-root.sh \
small-integration-test.sh \
mergedir.sh \
sample_delcache.sh \
sample_ahbe.conf
testdir = test
#
# 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
#

View File

@ -0,0 +1,2 @@
com.bouncestorage.chaoshttpproxy.http_503=1
com.bouncestorage.chaoshttpproxy.success=9

141
test/filter-suite-log.sh Executable file
View File

@ -0,0 +1,141 @@
#!/bin/bash
#
# s3fs - FUSE-based file system backed by Amazon S3
#
# Copyright 2007-2008 Randy Rizun <rrizun@gmail.com>
#
# 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.
#
func_usage()
{
echo ""
echo "Usage: $1 [-h] <log file path>"
echo " -h print help"
echo " log file path path for test-suite.log"
echo ""
}
PRGNAME=`basename $0`
SCRIPTDIR=`dirname $0`
S3FSDIR=`cd ${SCRIPTDIR}/..; pwd`
TOPDIR=`cd ${S3FSDIR}/test; pwd`
SUITELOG="${TOPDIR}/test-suite.log"
TMP_LINENO_FILE="/tmp/.lineno.tmp"
while [ $# -ne 0 ]; do
if [ "X$1" = "X" ]; then
break
elif [ "X$1" = "X-h" -o "X$1" = "X-H" -o "X$1" = "X--help" -o "X$1" = "X--HELP" ]; then
func_usage ${PRGNAME}
exit 0
else
SUITELOG=$1
fi
shift
done
if [ ! -f ${SUITELOG} ]; then
echo "[ERROR] not found ${SUITELOG} log file."
exit 1
fi
#
# Extract keyword line numbers and types
#
# 0 : normal line
# 1 : start line for one small test(specified in integration-test-main.sh)
# 2 : passed line of end of one small test(specified in test-utils.sh)
# 3 : failed line of end of one small test(specified in test-utils.sh)
#
grep -n -e 'test_.*: ".*"' -o -e 'test_.* passed' -o -e 'test_.* failed' ${SUITELOG} 2>/dev/null | sed 's/:test_.*: ".*"/ 1/g' | sed 's/:test_.* passed/ 2/g' | sed 's/:test_.* failed/ 3/g' > ${TMP_LINENO_FILE}
#
# Loop for printing result
#
prev_line_type=0
prev_line_number=1
while read line; do
# line is "<line number> <line type>"
number_type=($line)
head_line_cnt=`expr ${number_type[0]} - 1`
tail_line_cnt=`expr ${number_type[0]} - ${prev_line_number}`
if [ ${number_type[1]} -eq 2 ]; then
echo ""
fi
if [ ${prev_line_type} -eq 1 ]; then
if [ ${number_type[1]} -eq 2 ]; then
# if passed, cut s3fs information messages
head -${head_line_cnt} ${SUITELOG} | tail -${tail_line_cnt} | grep -v -e '[0-9]\+\%' | grep -v -e '^s3fs: ' -a -e '\[INF\]'
elif [ ${number_type[1]} -eq 3 ]; then
# if failed, print all
head -${head_line_cnt} ${SUITELOG} | tail -${tail_line_cnt} | grep -v -e '[0-9]\+\%'
else
# there is start keyword but not end keyword, so print all
head -${head_line_cnt} ${SUITELOG} | tail -${tail_line_cnt} | grep -v -e '[0-9]\+\%'
fi
elif [ ${prev_line_type} -eq 2 -o ${prev_line_type} -eq 3 ]; then
if [ ${number_type[1]} -eq 2 -o ${number_type[1]} -eq 3 ]; then
# previous is end of chmpx, but this type is end of chmpx without start keyword. then print all
head -${head_line_cnt} ${SUITELOG} | tail -${tail_line_cnt} | grep -v -e '[0-9]\+\%'
else
# this area is not from start to end, cut s3fs information messages
head -${head_line_cnt} ${SUITELOG} | tail -${tail_line_cnt} | grep -v -e '[0-9]\+\%' | grep -v -e '^s3fs: ' -a -e '\[INF\]'
fi
else
if [ ${number_type[1]} -eq 2 -o ${number_type[1]} -eq 3 ]; then
# previous is normal, but this type is end of chmpx without start keyword. then print all
head -${head_line_cnt} ${SUITELOG} | tail -${tail_line_cnt} | grep -v -e '[0-9]\+\%'
else
# this area is normal, cut s3fs information messages
head -${head_line_cnt} ${SUITELOG} | tail -${tail_line_cnt} | grep -v -e '[0-9]\+\%' | grep -v -e '^s3fs: ' -a -e '\[INF\]'
fi
fi
if [ ${number_type[1]} -eq 3 ]; then
echo ""
fi
prev_line_type=${number_type[1]}
prev_line_number=${number_type[0]}
done < ${TMP_LINENO_FILE}
#
# Print rest lines
#
file_line_cnt=`wc -l ${SUITELOG} | awk '{print $1}'`
tail_line_cnt=`expr ${file_line_cnt} - ${prev_line_number}`
if [ ${prev_line_type} -eq 1 ]; then
tail -${tail_line_cnt} ${SUITELOG} | grep -v -e '[0-9]\+\%'
else
tail -${tail_line_cnt} ${SUITELOG} | grep -v -e '[0-9]\+\%' | grep -v -e '^s3fs: ' -a -e '\[INF\]'
fi
#
# Remove temp file
#
rm -f ${TMP_LINENO_FILE}
exit 0
#
# 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
#

View File

@ -1,14 +1,325 @@
#!/bin/bash -e
#!/bin/bash
#
# s3fs - FUSE-based file system backed by Amazon S3
#
# Copyright 2007-2008 Randy Rizun <rrizun@gmail.com>
#
# 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.
#
#
# Common code for starting an s3fs-fuse mountpoint and an S3Proxy instance
# to run tests against S3Proxy locally.
#
# To run against an Amazon S3 or other S3 provider, specify the following
# environment variables:
#
# S3FS_CREDENTIALS_FILE=keyfile s3fs format key file
# S3FS_PROFILE=name s3fs profile to use (overrides key file)
# TEST_BUCKET_1=bucketname Name of bucket to use
# S3PROXY_BINARY="" Specify empty string to skip S3Proxy start
# S3_URL="https://s3.amazonaws.com" Specify Amazon AWS as the S3 provider
# S3_ENDPOINT="us-east-1" Specify region
# TMPDIR="/var/tmp" Set to use a temporary directory different
# from /var/tmp
#
# Example of running against Amazon S3 using a bucket named "bucket":
#
# S3FS_CREDENTIALS_FILE=keyfile TEST_BUCKET_1=bucket S3PROXY_BINARY="" S3_URL="https://s3.amazonaws.com" ./small-integration-test.sh
#
# To change the s3fs-fuse debug level:
#
# DBGLEVEL=debug ./small-integration-test.sh
#
# To stop and wait after the mount point is up for manual interaction. This allows you to
# explore the mounted file system exactly as it would have been started for the test case
#
# INTERACT=1 DBGLEVEL=debug ./small-integration-test.sh
#
# Run all of the tests from the makefile
#
# S3FS_CREDENTIALS_FILE=keyfile TEST_BUCKET_1=bucket S3PROXY_BINARY="" S3_URL="https://s3.amazonaws.com" make check
#
# Run the tests with request auth turned off in both S3Proxy and s3fs-fuse. This can be
# useful for poking around with plain old curl
#
# PUBLIC=1 INTERACT=1 ./small-integration-test.sh
#
# A valgrind tool can be specified
# eg: VALGRIND="--tool=memcheck --leak-check=full" ./small-integration-test.sh
set -o errexit
set -o pipefail
S3FS=../src/s3fs
S3FS_CREDENTIALS_FILE=$(eval echo ~${SUDO_USER}/.passwd-s3fs)
# Allow these defaulted values to be overridden
: ${S3_URL:="https://127.0.0.1:8080"}
: ${S3_ENDPOINT:="us-east-1"}
: ${S3FS_CREDENTIALS_FILE:="passwd-s3fs"}
: ${TEST_BUCKET_1:="s3fs-integration-test"}
TEST_BUCKET_1=${SUDO_USER}-s3fs-integration-test
TEST_BUCKET_MOUNT_POINT_1=/mnt/${TEST_BUCKET_1}
export TEST_BUCKET_1
export S3_URL
export S3_ENDPOINT
export TEST_SCRIPT_DIR=`pwd`
export TEST_BUCKET_MOUNT_POINT_1=${TEST_BUCKET_1}
S3PROXY_VERSION="1.8.0"
S3PROXY_BINARY=${S3PROXY_BINARY-"s3proxy-${S3PROXY_VERSION}"}
CHAOS_HTTP_PROXY_VERSION="1.1.0"
CHAOS_HTTP_PROXY_BINARY="chaos-http-proxy-${CHAOS_HTTP_PROXY_VERSION}"
if [ ! -f "$S3FS_CREDENTIALS_FILE" ]
then
echo "Missing credentials file: $S3FS_CREDENTIALS_FILE"
exit 1
fi
chmod 600 "$S3FS_CREDENTIALS_FILE"
if [ -z "${S3FS_PROFILE}" ]; then
export AWS_ACCESS_KEY_ID=$(cut -d: -f1 ${S3FS_CREDENTIALS_FILE})
export AWS_SECRET_ACCESS_KEY=$(cut -d: -f2 ${S3FS_CREDENTIALS_FILE})
fi
if [ ! -d $TEST_BUCKET_MOUNT_POINT_1 ]
then
mkdir -p $TEST_BUCKET_MOUNT_POINT_1
fi
# This function execute the function parameters $1 times
# before giving up, with 1 second delays.
function retry {
set +o errexit
N=$1; shift;
status=0
for i in $(seq $N); do
echo "Trying: $*"
eval $@
status=$?
if [ $status == 0 ]; then
break
fi
sleep 1
echo "Retrying: $*"
done
if [ $status != 0 ]; then
echo "timeout waiting for $*"
fi
set -o errexit
return $status
}
# Proxy is not started if S3PROXY_BINARY is an empty string
# PUBLIC unset: use s3proxy.conf
# PUBLIC=1: use s3proxy-noauth.conf (no request signing)
#
function start_s3proxy {
if [ -n "${PUBLIC}" ]; then
S3PROXY_CONFIG="s3proxy-noauth.conf"
else
S3PROXY_CONFIG="s3proxy.conf"
fi
if [ -n "${S3PROXY_BINARY}" ]
then
if [ ! -e "${S3PROXY_BINARY}" ]; then
wget "https://github.com/gaul/s3proxy/releases/download/s3proxy-${S3PROXY_VERSION}/s3proxy" \
--quiet -O "${S3PROXY_BINARY}"
chmod +x "${S3PROXY_BINARY}"
fi
${STDBUF_BIN} -oL -eL java -jar "$S3PROXY_BINARY" --properties $S3PROXY_CONFIG &
S3PROXY_PID=$!
# wait for S3Proxy to start
wait_for_port 8080
fi
if [ -n "${CHAOS_HTTP_PROXY}" ]; then
if [ ! -e "${CHAOS_HTTP_PROXY_BINARY}" ]; then
wget "https://github.com/bouncestorage/chaos-http-proxy/releases/download/chaos-http-proxy-${CHAOS_HTTP_PROXY_VERSION}/chaos-http-proxy" \
--quiet -O "${CHAOS_HTTP_PROXY_BINARY}"
chmod +x "${CHAOS_HTTP_PROXY_BINARY}"
fi
${STDBUF_BIN} -oL -eL java -jar ${CHAOS_HTTP_PROXY_BINARY} --properties chaos-http-proxy.conf &
CHAOS_HTTP_PROXY_PID=$!
# wait for Chaos HTTP Proxy to start
wait_for_port 1080
fi
}
function stop_s3proxy {
if [ -n "${S3PROXY_PID}" ]
then
kill $S3PROXY_PID
fi
if [ -n "${CHAOS_HTTP_PROXY_PID}" ]
then
kill $CHAOS_HTTP_PROXY_PID
fi
}
# Mount the bucket, function arguments passed to s3fs in addition to
# a set of common arguments.
function start_s3fs {
# Public bucket if PUBLIC is set
if [ -n "${PUBLIC}" ]; then
AUTH_OPT="-o public_bucket=1"
elif [ -n "${S3FS_PROFILE}" ]; then
AUTH_OPT="-o profile=${S3FS_PROFILE}"
else
AUTH_OPT="-o passwd_file=${S3FS_CREDENTIALS_FILE}"
fi
# If VALGRIND is set, pass it as options to valgrind.
# start valgrind-listener in another shell.
# eg: VALGRIND="--tool=memcheck --leak-check=full" ./small-integration-test.sh
# Start valgrind-listener (default port is 1500)
if [ -n "${VALGRIND}" ]; then
VALGRIND_EXEC="valgrind ${VALGRIND} --log-socket=127.0.1.1"
fi
# On OSX only, we need to specify the direct_io and auto_cache flag.
if [ `uname` = "Darwin" ]; then
DIRECT_IO_OPT="-o direct_io -o auto_cache"
else
DIRECT_IO_OPT=""
fi
if [ -n "${CHAOS_HTTP_PROXY}" ]; then
export http_proxy="127.0.0.1:1080"
fi
# [NOTE]
# On macos, running s3fs via stdbuf will result in no response.
# Therefore, when it is macos, it is not executed via stdbuf.
# This patch may be temporary, but no other method has been found at this time.
#
if [ `uname` = "Darwin" ]; then
VIA_STDBUF_CMDLINE=""
else
VIA_STDBUF_CMDLINE="${STDBUF_BIN} -oL -eL"
fi
# Common s3fs options:
#
# TODO: Allow all these options to be overridden with env variables
#
# use_path_request_style
# The test env doesn't have virtual hosts
# createbucket
# S3Proxy always starts with no buckets, this tests the s3fs-fuse
# automatic bucket creation path.
# $AUTH_OPT
# Will be either "-o public_bucket=1"
# or
# "-o passwd_file=${S3FS_CREDENTIALS_FILE}"
# dbglevel
# error by default. override with DBGLEVEL env variable
# -f
# Keep s3fs in foreground instead of daemonizing
#
# subshell with set -x to log exact invocation of s3fs-fuse
(
set -x
${VIA_STDBUF_CMDLINE} \
${VALGRIND_EXEC} ${S3FS} \
$TEST_BUCKET_1 \
$TEST_BUCKET_MOUNT_POINT_1 \
-o use_path_request_style \
-o url=${S3_URL} \
-o endpoint=${S3_ENDPOINT} \
-o no_check_certificate \
-o ssl_verify_hostname=0 \
-o use_xattr=1 \
-o createbucket \
${AUTH_OPT} \
${DIRECT_IO_OPT} \
-o stat_cache_expire=1 \
-o stat_cache_interval_expire=1 \
-o dbglevel=${DBGLEVEL:=info} \
-o no_time_stamp_msg \
-o retries=3 \
-f \
"${@}" &
echo $! >&3
) 3>pid | ${STDBUF_BIN} -oL -eL ${SED_BIN} ${SED_BUFFER_FLAG} "s/^/s3fs: /" &
sleep 1
export S3FS_PID=$(<pid)
rm -f pid
if [ `uname` = "Darwin" ]; then
set +o errexit
TRYCOUNT=0
while [ $TRYCOUNT -le ${RETRIES:=20} ]; do
df | grep -q $TEST_BUCKET_MOUNT_POINT_1
if [ $? -eq 0 ]; then
break;
fi
sleep 1
TRYCOUNT=`expr ${TRYCOUNT} + 1`
done
if [ $? -ne 0 ]; then
exit 1
fi
set -o errexit
else
retry ${RETRIES:=20} grep -q $TEST_BUCKET_MOUNT_POINT_1 /proc/mounts || exit 1
fi
# Quick way to start system up for manual testing with options under test
if [[ -n ${INTERACT} ]]; then
echo "Mountpoint $TEST_BUCKET_MOUNT_POINT_1 is ready"
echo "control-C to quit"
sleep infinity
exit 0
fi
}
function stop_s3fs {
# Retry in case file system is in use
if [ `uname` = "Darwin" ]; then
if df | grep -q $TEST_BUCKET_MOUNT_POINT_1; then
retry 10 df "|" grep -q $TEST_BUCKET_MOUNT_POINT_1 "&&" umount $TEST_BUCKET_MOUNT_POINT_1
fi
else
if grep -q $TEST_BUCKET_MOUNT_POINT_1 /proc/mounts; then
retry 10 grep -q $TEST_BUCKET_MOUNT_POINT_1 /proc/mounts "&&" fusermount -u $TEST_BUCKET_MOUNT_POINT_1
fi
fi
}
# trap handlers do not stack. If a test sets its own, the new handler should call common_exit_handler
function common_exit_handler {
stop_s3fs
stop_s3proxy
}
trap common_exit_handler EXIT
#
# 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
#

1535
test/integration-test-main.sh Executable file

File diff suppressed because it is too large Load Diff

BIN
test/keystore.jks Normal file

Binary file not shown.

View File

@ -1,4 +1,24 @@
#!/bin/sh
#
# s3fs - FUSE-based file system backed by Amazon S3
#
# Copyright 2007-2008 Randy Rizun <rrizun@gmail.com>
#
# 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.
#
#
# Merge old directory object to new.
# For s3fs after v1.64
@ -7,12 +27,12 @@
###
### UsageFunction <program name>
###
UsageFuntion()
UsageFunction()
{
echo "Usage: $1 [-h] [-y] [-all] <base directory>"
echo " -h print usage"
echo " -y no confirm"
echo " -all force all directoris"
echo " -all force all directories"
echo " There is no -all option is only to merge for other S3 client."
echo " If -all is specified, this shell script merge all directory"
echo " for s3fs old version."
@ -28,7 +48,7 @@ DIRPARAM=""
while [ "$1" != "" ]; do
if [ "X$1" = "X-help" -o "X$1" = "X-h" -o "X$1" = "X-H" ]; then
UsageFuntion $OWNNAME
UsageFunction $OWNNAME
exit 0
elif [ "X$1" = "X-y" -o "X$1" = "X-Y" ]; then
AUTOYES="yes"
@ -38,7 +58,7 @@ while [ "$1" != "" ]; do
if [ "X$DIRPARAM" != "X" ]; then
echo "*** Input error."
echo ""
UsageFuntion $OWNNAME
UsageFunction $OWNNAME
exit 1
fi
DIRPARAM=$1
@ -48,7 +68,7 @@ done
if [ "X$DIRPARAM" = "X" ]; then
echo "*** Input error."
echo ""
UsageFuntion $OWNNAME
UsageFunction $OWNNAME
exit 1
fi
@ -62,7 +82,7 @@ fi
echo "#############################################################################"
echo "[CAUTION]"
echo "This program merges a directory made in s3fs which is older than version 1.64."
echo "And made in other S3 client appilication."
echo "And made in other S3 client application."
echo "This program may be have bugs which are not fixed yet."
echo "Please execute this program by responsibility of your own."
echo "#############################################################################"
@ -104,7 +124,7 @@ for DIR in $DIRLIST; do
if [ "$ALLYES" = "no" ]; then
### Skip "d---------" directories.
### Other clients make directory object "dir/" which don't have
### "x-amz-meta-mode" attribyte.
### "x-amz-meta-mode" attribute.
### Then these directories is "d---------", it is target directory.
DIRPERMIT=`ls -ld --time-style=+'%Y%m%d%H%M' $DIR | awk '{print $1}'`
if [ "$DIRPERMIT" != "d---------" ]; then
@ -112,7 +132,7 @@ for DIR in $DIRLIST; do
fi
fi
### Comfirm
### Confirm
ANSWER=""
if [ "$AUTOYES" = "yes" ]; then
ANSWER="y"
@ -165,5 +185,10 @@ echo -n "# Finished : " >> $LOGFILE
echo `date` >> $LOGFILE
#
# END
# 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
#

1
test/passwd-s3fs Normal file
View File

@ -0,0 +1 @@
local-identity:local-credential

View File

@ -1,7 +1,35 @@
#!/bin/bash -e
#
# s3fs - FUSE-based file system backed by Amazon S3
#
# Copyright 2007-2008 Randy Rizun <rrizun@gmail.com>
#
# 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.
#
if [[ $EUID -ne 0 ]]
then
echo "This test script must be run as root" 1>&2
exit 1
fi
#
# 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
#

View File

@ -0,0 +1,66 @@
#!/bin/bash
#
# s3fs - FUSE-based file system backed by Amazon S3
#
# Copyright 2007-2008 Randy Rizun <rrizun@gmail.com>
#
# 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.
#
set -o errexit
set -o nounset
set -o pipefail
# Disable preprocessor warnings from _FORTIFY_SOURCE and -O0
COMMON_FLAGS="-g -O0 -Wno-cpp"
# run tests with libstc++ debug mode, https://gcc.gnu.org/onlinedocs/libstdc++/manual/debug_mode.html
make clean
./configure CXXFLAGS="$COMMON_FLAGS -D_GLIBCXX_DEBUG"
make
DBGLEVEL=debug make check -C test/
# run tests under AddressSanitizer, https://clang.llvm.org/docs/AddressSanitizer.html
make clean
./configure CXX=clang++ CXXFLAGS="$COMMON_FLAGS -fsanitize=address -fsanitize-address-use-after-scope"
make
ASAN_OPTIONS='detect_leaks=1,detect_stack_use_after_return=1' make check -C test/
# run tests under MemorySanitizer, https://clang.llvm.org/docs/MemorySanitizer.html
#make clean
#./configure CXX=clang++ CXXFLAGS="$COMMON_FLAGS -fsanitize=memory"
#make
#make check -C test/
# run tests under ThreadSanitizer, https://clang.llvm.org/docs/ThreadSanitizer.html
make clean
./configure CXX=clang++ CXXFLAGS="$COMMON_FLAGS -fsanitize=thread"
make
TSAN_OPTIONS='halt_on_error=1' make check -C test/
# run tests under UndefinedBehaviorSanitizer, https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
make clean
./configure CXX=clang++ CXXFLAGS="$COMMON_FLAGS -fsanitize=undefined,implicit-conversion,local-bounds,unsigned-integer-overflow"
make
make check -C test/
#
# 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
#

10
test/s3proxy.conf Normal file
View File

@ -0,0 +1,10 @@
s3proxy.secure-endpoint=https://127.0.0.1:8080
s3proxy.authorization=aws-v2-or-v4
s3proxy.identity=local-identity
s3proxy.credential=local-credential
s3proxy.keystore-path=keystore.jks
s3proxy.keystore-password=password
jclouds.provider=transient
jclouds.identity=remote-identity
jclouds.credential=remote-credential

View File

@ -1,24 +1,30 @@
# S3FS: Samlpe ahbe_conf parameter file.
# S3FS: Sample ahbe_conf parameter file.
#
# This file is configuration file for additional header by extension(ahbe).
# s3fs loads this file at starting.
#
# Format:
# line = [file suffix] HTTP-header [HTTP-header-values]
# line = [file suffix or regex] HTTP-header [HTTP-header-values]
# file suffix = file(object) suffix, if this field is empty,
# it means "*"(all object).
# it means "reg:(.*)".(=all object).
# regex = regular expression to match the file(object) path.
# this type starts with "reg:" prefix.
# HTTP-header = additional HTTP header name
# HTTP-header-values = additional HTTP header value
#
# <suffix(extension)> <HTTP header> <HTTP header values>
#
# Verification is done in the order in which they are described in the file.
# That order is very important.
#
# Example:
# " Content-Encoding gzip" --> all object
# ".gz Content-Encoding gzip" --> only ".gz" extension file
# " Content-Encoding gzip" --> all object
# ".gz Content-Encoding gzip" --> only ".gz" extension file
# "reg:^/DIR/(.*).t2$ Content-Encoding text2" --> "/DIR/*.t2" extension file
#
# Notice:
# If you need to set all object, you can specify without "suffix".
# Then all of object(file) is added additional header.
# If you need to set all object, you can specify without "suffix" or regex
# type "reg:(.*)". Then all of object(file) is added additional header.
# If you have this configuration file for Content-Encoding, you should
# know about RFC 2616.
#
@ -27,15 +33,20 @@
# Encoding header, and SHOULD NOT be used in the Content-Encoding
# header."
#
.gz Content-Encoding gzip
.Z Content-Encoding compress
.bz2 Content-Encoding bzip2
.svgz Content-Encoding gzip
.svg.gz Content-Encoding gzip
.tgz Content-Encoding gzip
.tar.gz Content-Encoding gzip
.taz Content-Encoding gzip
.tz Content-Encoding gzip
.tbz2 Content-Encoding gzip
gz.js Content-Encoding gzip
# file suffix type
.gz Content-Encoding gzip
.Z Content-Encoding compress
.bz2 Content-Encoding bzip2
.svgz Content-Encoding gzip
.svg.gz Content-Encoding gzip
.tgz Content-Encoding gzip
.tar.gz Content-Encoding gzip
.taz Content-Encoding gzip
.tz Content-Encoding gzip
.tbz2 Content-Encoding gzip
gz.js Content-Encoding gzip
# regex type(test)
reg:^/MYDIR/(.*)[.]t2$ Content-Encoding text2

Some files were not shown because too many files have changed in this diff Show More