Showing preview only (2,993K chars total). Download the full file or copy to clipboard to get everything.
Repository: haiwen/seafile-server
Branch: master
Commit: 377d6e5805ad
Files: 284
Total size: 2.8 MB
Directory structure:
gitextract_lx6ttehu/
├── .github/
│ └── workflows/
│ ├── ci.yml
│ └── golangci-lint.yml
├── .gitignore
├── LICENSE.txt
├── Makefile.am
├── README.markdown
├── README.testing.md
├── autogen.sh
├── ci/
│ ├── install-deps.sh
│ ├── requirements.txt
│ ├── run.py
│ ├── serverctl.py
│ └── utils.py
├── common/
│ ├── Makefile.am
│ ├── block-backend-fs.c
│ ├── block-backend.c
│ ├── block-backend.h
│ ├── block-mgr.c
│ ├── block-mgr.h
│ ├── block-tx-utils.c
│ ├── block-tx-utils.h
│ ├── block.h
│ ├── branch-mgr.c
│ ├── branch-mgr.h
│ ├── cdc/
│ │ ├── Makefile.am
│ │ ├── cdc.c
│ │ ├── cdc.h
│ │ ├── rabin-checksum.c
│ │ └── rabin-checksum.h
│ ├── commit-mgr.c
│ ├── commit-mgr.h
│ ├── common.h
│ ├── config-mgr.c
│ ├── config-mgr.h
│ ├── diff-simple.c
│ ├── diff-simple.h
│ ├── fs-mgr.c
│ ├── fs-mgr.h
│ ├── group-mgr.c
│ ├── group-mgr.h
│ ├── log.c
│ ├── log.h
│ ├── merge-new.c
│ ├── merge-new.h
│ ├── mq-mgr.c
│ ├── mq-mgr.h
│ ├── obj-backend-fs.c
│ ├── obj-backend-riak.c
│ ├── obj-backend.h
│ ├── obj-cache.c
│ ├── obj-cache.h
│ ├── obj-store.c
│ ├── obj-store.h
│ ├── object-list.c
│ ├── object-list.h
│ ├── org-mgr.c
│ ├── org-mgr.h
│ ├── password-hash.c
│ ├── password-hash.h
│ ├── processors/
│ │ └── objecttx-common.h
│ ├── redis-cache.c
│ ├── redis-cache.h
│ ├── rpc-service.c
│ ├── seaf-db.c
│ ├── seaf-db.h
│ ├── seaf-utils.c
│ ├── seaf-utils.h
│ ├── seafile-crypt.c
│ ├── seafile-crypt.h
│ ├── sync-repo-common.h
│ ├── user-mgr.c
│ ├── user-mgr.h
│ ├── vc-common.c
│ └── vc-common.h
├── configure.ac
├── controller/
│ ├── Makefile.am
│ ├── seafile-controller.c
│ └── seafile-controller.h
├── doc/
│ └── Makefile.am
├── fileserver/
│ ├── .golangci.yml
│ ├── blockmgr/
│ │ ├── blockmgr.go
│ │ └── blockmgr_test.go
│ ├── commitmgr/
│ │ ├── commitmgr.go
│ │ ├── commitmgr_test.go
│ │ └── null.go
│ ├── crypt.go
│ ├── diff/
│ │ ├── diff.go
│ │ └── diff_test.go
│ ├── fileop.go
│ ├── fileserver.go
│ ├── fsmgr/
│ │ ├── fsmgr.go
│ │ └── fsmgr_test.go
│ ├── go.mod
│ ├── go.sum
│ ├── http_code.go
│ ├── merge.go
│ ├── merge_test.go
│ ├── metrics/
│ │ └── metrics.go
│ ├── objstore/
│ │ ├── backend_fs.go
│ │ ├── objstore.go
│ │ └── objstore_test.go
│ ├── option/
│ │ └── option.go
│ ├── quota.go
│ ├── repomgr/
│ │ ├── repomgr.go
│ │ └── repomgr_test.go
│ ├── searpc/
│ │ ├── searpc.go
│ │ └── searpc_test.go
│ ├── share/
│ │ ├── group/
│ │ │ └── group.go
│ │ ├── public/
│ │ │ └── public.go
│ │ └── share.go
│ ├── size_sched.go
│ ├── sync_api.go
│ ├── utils/
│ │ ├── dup2.go
│ │ ├── dup3.go
│ │ ├── http.go
│ │ └── utils.go
│ ├── virtual_repo.go
│ └── workerpool/
│ └── workerpool.go
├── fuse/
│ ├── Makefile.am
│ ├── file.c
│ ├── getattr.c
│ ├── readdir.c
│ ├── repo-mgr.c
│ ├── repo-mgr.h
│ ├── seaf-fuse.c
│ ├── seaf-fuse.h
│ ├── seafile-session.c
│ └── seafile-session.h
├── include/
│ ├── Makefile.am
│ ├── seafile-error.h
│ └── seafile-rpc.h
├── lib/
│ ├── Makefile.am
│ ├── bloom-filter.c
│ ├── bloom-filter.h
│ ├── branch.vala
│ ├── ccnetobj.vala
│ ├── commit.vala
│ ├── copy-task.vala
│ ├── crypt.vala
│ ├── db.c
│ ├── db.h
│ ├── dir.vala
│ ├── dirent.vala
│ ├── file.vala
│ ├── include.h
│ ├── job-mgr.c
│ ├── job-mgr.h
│ ├── libseafile.pc.in
│ ├── net.c
│ ├── net.h
│ ├── repo.vala
│ ├── rpc_table.py
│ ├── seahub.vala
│ ├── search-result.vala
│ ├── task.vala
│ ├── timer.c
│ ├── timer.h
│ ├── utils.c
│ ├── utils.h
│ └── webaccess.vala
├── m4/
│ ├── ax_lib_sqlite3.m4
│ ├── glib-gettext.m4
│ └── python.m4
├── notification-server/
│ ├── .golangci.yml
│ ├── ccnet.conf
│ ├── client.go
│ ├── dup2.go
│ ├── dup3.go
│ ├── event.go
│ ├── go.mod
│ ├── go.sum
│ ├── logger.go
│ ├── server.go
│ └── subscriptions.go
├── pytest.ini
├── python/
│ ├── LICENSE.txt
│ ├── Makefile.am
│ ├── seafile/
│ │ ├── Makefile.am
│ │ ├── __init__.py
│ │ └── rpcclient.py
│ └── seaserv/
│ ├── Makefile.am
│ ├── __init__.py
│ ├── api.py
│ └── service.py
├── run_tests.sh
├── scripts/
│ ├── Makefile.am
│ ├── parse_seahub_db.py
│ └── sql/
│ ├── mysql/
│ │ ├── ccnet.sql
│ │ └── seafile.sql
│ └── sqlite/
│ ├── config.sql
│ ├── groupmgr.sql
│ ├── org.sql
│ ├── seafile.sql
│ └── user.sql
├── server/
│ ├── Makefile.am
│ ├── access-file.c
│ ├── access-file.h
│ ├── change-set.c
│ ├── change-set.h
│ ├── copy-mgr.c
│ ├── copy-mgr.h
│ ├── fileserver-config.c
│ ├── fileserver-config.h
│ ├── gc/
│ │ ├── Makefile.am
│ │ ├── fsck.c
│ │ ├── fsck.h
│ │ ├── gc-core.c
│ │ ├── gc-core.h
│ │ ├── repo-mgr.c
│ │ ├── repo-mgr.h
│ │ ├── seaf-fsck.c
│ │ ├── seafile-session.c
│ │ ├── seafile-session.h
│ │ ├── seafserv-gc.c
│ │ ├── verify.c
│ │ └── verify.h
│ ├── http-server.c
│ ├── http-server.h
│ ├── http-status-codes.h
│ ├── http-tx-mgr.c
│ ├── http-tx-mgr.h
│ ├── index-blocks-mgr.c
│ ├── index-blocks-mgr.h
│ ├── metric-mgr.c
│ ├── metric-mgr.h
│ ├── notif-mgr.c
│ ├── notif-mgr.h
│ ├── pack-dir.c
│ ├── pack-dir.h
│ ├── passwd-mgr.c
│ ├── passwd-mgr.h
│ ├── permission-mgr.c
│ ├── permission-mgr.h
│ ├── quota-mgr.c
│ ├── quota-mgr.h
│ ├── repo-mgr.c
│ ├── repo-mgr.h
│ ├── repo-op.c
│ ├── repo-perm.c
│ ├── seaf-server.c
│ ├── seafile-session.c
│ ├── seafile-session.h
│ ├── share-mgr.c
│ ├── share-mgr.h
│ ├── size-sched.c
│ ├── size-sched.h
│ ├── upload-file.c
│ ├── upload-file.h
│ ├── virtual-repo.c
│ ├── web-accesstoken-mgr.c
│ ├── web-accesstoken-mgr.h
│ ├── zip-download-mgr.c
│ └── zip-download-mgr.h
├── tests/
│ ├── __init__.py
│ ├── conf/
│ │ ├── ccnet.conf
│ │ └── mykey.peer
│ ├── config.py
│ ├── conftest.py
│ ├── test_file_operation/
│ │ ├── test_file_operation.py
│ │ ├── test_merge_virtual_repo.py
│ │ ├── test_search_files.py
│ │ ├── test_upload_and_update.py
│ │ ├── test_upload_large_files.py
│ │ └── test_zip_download.py
│ ├── test_file_property_and_dir_listing/
│ │ └── test_file_property_and_dir_listing.py
│ ├── test_gc/
│ │ └── test_gc.py
│ ├── test_get_repo_list/
│ │ └── test_get_repo_list.py
│ ├── test_group/
│ │ └── test_groups.py
│ ├── test_password/
│ │ └── test_password.py
│ ├── test_repo_manipulation/
│ │ └── test_repo_manipulation.py
│ ├── test_server_config/
│ │ └── test_server_config.py
│ ├── test_share_and_perm/
│ │ ├── test_shared_repo_perm.py
│ │ └── test_structure_repo_perm.py
│ ├── test_trashed_repos/
│ │ └── test_trashed_repos.py
│ ├── test_upload/
│ │ ├── account.conf
│ │ ├── go.mod
│ │ ├── go.sum
│ │ ├── readme.md
│ │ └── test_upload.go
│ ├── test_user/
│ │ └── test_users.py
│ └── utils.py
├── tools/
│ ├── Makefile.am
│ └── seafile-admin
└── updateversion.sh
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/ci.yml
================================================
name: Seafile CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
with:
fetch-depth: 1
- uses: actions/setup-python@v3
with:
python-version: "3.12"
- name: install dependencies and test
run: |
cd $GITHUB_WORKSPACE
./ci/install-deps.sh
./ci/run.py
================================================
FILE: .github/workflows/golangci-lint.yml
================================================
name: golangci-lint
on: [push, pull_request]
permissions:
contents: read
# Optional: allow read access to pull request. Use with `only-new-issues` option.
# pull-requests: read
jobs:
golangci-fileserver:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: "1.22"
- name: golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: v1.59
working-directory: ./fileserver
args: --timeout=5m
golangci-notification-server:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: "1.22"
- name: golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: v1.59
working-directory: ./notification-server
args: --timeout=5m
================================================
FILE: .gitignore
================================================
*~
*.bak
*.o
*.exe
cscope*
*#
Makefile.in
ltmain.sh
libtool
*.lo
*.la
install-sh
depcomp
config.guess
config.h
config.log
config.status
config.sub
config.cache
configure
*/.deps
autom4te*
po/POTFILES
po/Makefile*
po/stamp-it
po/*.gmo
po/*.pot
missing
mkinstalldirs
stamp-h1
*.libs/
Makefile
aclocal.m4
*core
m4/intltool.m4
m4/libtool.m4
m4/ltoptions.m4
m4/ltsugar.m4
m4/ltversion.m4
m4/lt~obsolete.m4
ccnet-*.tar.gz
config.h.in
py-compile
intltool-extract.in
intltool-merge.in
intltool-update.in
*.stamp
*.pyc
*.tmp.ui
*.defs
*.log
.deps
*.db
*.dll
*.aps
*.so
build-stamp
debian/files
debian/seafile
debian/*.substvars
lib/searpc-marshal.h
lib/searpc-signature.h
lib/*.tmp
lib/dir.c
lib/dirent.c
lib/seafile-object.h
lib/task.c
lib/webaccess.c
lib/branch.c
lib/commit.c
lib/crypt.c
lib/repo.c
lib/copy-task.c
lib/search-result.c
seaf-server
seafserv-gc
seaf-migrate
seaf-fsck
seaf-fuse
controller/seafile-controller
tools/seaf-server-init
tests/conf/misc/
tests/conf/seafile-data/
tests/conf/ccnet.db
tests/conf/ccnet.sock
tests/conf/GroupMgr
tests/conf/OrgMgr
tests/conf/PeerMgr
*.dylib
.DS_Store
*.pc
*.tar.gz
/compile
/test-driver
*.dmp
/symbols
__pycache__/
.cache/
================================================
FILE: LICENSE.txt
================================================
This program is released under Affero GPLv3, with the following additional
permission to link with OpenSSL library.
If you modify this program, or any covered work, by linking or
combining it with the OpenSSL project's OpenSSL library (or a
modified version of that library), containing parts covered by the
terms of the OpenSSL or SSLeay licenses, Seafile Ltd.
grants you additional permission to convey the resulting work.
Corresponding Source for a non-source form of such a combination
shall include the source code for the parts of OpenSSL used as well
as that of the covered work.
The source code files under 'python' directory is released under
Apache License v2.0. You can find Apache License 2.0 file in that
directory.
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright © 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.
Preamble
The GNU Affero General Public License is a free, copyleft license for software and other kinds of works, specifically designed to ensure cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, our General Public Licenses are intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users.
When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things.
Developers that use our General Public Licenses protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License which gives you legal permission to copy, distribute and/or modify the software.
A secondary benefit of defending all users' freedom is that improvements made in alternate versions of the program, if they receive widespread use, become available for other developers to incorporate. Many developers of free software are heartened and encouraged by the resulting cooperation. However, in the case of software used on network servers, this result may fail to come about. The GNU General Public License permits making a modified version and letting the public access it on a server without ever releasing its source code to the public.
The GNU Affero General Public License is designed specifically to ensure that, in such cases, the modified source code becomes available to the community. It requires the operator of a network server to provide the source code of the modified version running there to the users of that server. Therefore, public use of a modified version, on a publicly accessible server, gives the public access to the source code of the modified version.
An older license, called the Affero General Public License and published by Affero, was designed to accomplish similar goals. This is a different license, not a version of the Affero GPL, but Affero has released a new version of the Affero GPL which permits relicensing under this license.
The precise terms and conditions for copying, distribution and modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU Affero General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based on the Program.
To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work.
A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work.
The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source.
The Corresponding Source for a work in source code form is that same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures.
When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified it, and giving a relevant date.
b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices".
c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so.
A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways:
a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b.
d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d.
A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product.
"Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made.
If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM).
The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or authors of the material; or
e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors.
All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11).
However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.
Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party.
If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it.
A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the Program, your modified version must prominently offer all users interacting with it remotely through a computer network (if your version supports such interaction) an opportunity to receive the Corresponding Source of your version by providing access to the Corresponding Source from a network server at no charge, through some standard or customary means of facilitating copying of software. This Corresponding Source shall include the Corresponding Source for any work covered by version 3 of the GNU General Public License that is incorporated pursuant to the following paragraph.
Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the work with which it is combined will remain governed by version 3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of the GNU Affero General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU Affero General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU Affero General Public License, you may choose any version ever published by the Free Software Foundation.
If the Program specifies that a proxy can decide which future versions of the GNU Affero General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program.
Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer network, you should also make sure that it provides a way for users to get its source. For example, if your program is a web application, its interface could display a "Source" link that leads users to an archive of the code. There are many ways you could offer source, and different solutions will be better for different programs; see section 13 for the specific requirements.
You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU AGPL, see <http://www.gnu.org/licenses/>.
================================================
FILE: Makefile.am
================================================
MAKE_CLIENT =
if WIN32
MAKE_CONTROLLER =
else
MAKE_CONTROLLER = controller
endif
if COMPILE_FUSE
MAKE_FUSE = fuse
else
MAKE_FUSE =
endif
MAKE_SERVER = server tools $(MAKE_CONTROLLER) $(MAKE_FUSE)
SUBDIRS = include lib common python $(MAKE_SERVER) doc scripts
DIST_SUBDIRS = include lib common python server tools controller fuse doc scripts
INTLTOOL = \
intltool-extract.in \
intltool-merge.in \
intltool-update.in
EXTRA_DIST = install-sh $(INTLTOOL) README.markdown scripts LICENSE.txt
ACLOCAL_AMFLAGS = -I m4
dist-hook:
git log --format='%H' -1 > $(distdir)/latest_commit
================================================
FILE: README.markdown
================================================
Seafile Server Core [](http://travis-ci.org/haiwen/seafile-server)
============
Seafile is an open source cloud storage system with features on privacy protection and teamwork. Collections of files are called libraries, and each library can be synced separately. A library can also be encrypted with a user chosen password. Seafile also allows users to create groups and easily sharing files into groups.
This is the core component of Seafile server. It provides RPC to the web front-end (Seahub) to access files, and provides HTTP APIs to the desktop clients for syncing files.
Build and Run
=============
See <https://manual.seafile.com/build_seafile/server/>
Contributing
===========
For more informations read [Contribution](https://manual.seafile.com/contribution/).
License
=======
The Seafile server core is published under AGPLv3. Other components of Seafile have different licenses. Please refer to the coresponding projects.
Contact
=======
Twitter: @seafile <https://twitter.com/seafile>
Forum: <https://forum.seafile.com>
================================================
FILE: README.testing.md
================================================
# Seafile Server Tests
## Run it locally
To run the tests, you need to install pytest first:
```sh
pip install -r ci/requirements.txt
```
Compile and install ccnet-server and seafile-server
```
cd ccnet-server
make
sudo make install
cd seafile-server
make
sudo make install
```
Then run the tests with
```sh
cd seafile-server
./run_tests.sh
```
By default the test script would try to start ccnet-server and seaf-server in `/usr/local/bin`, if you `make install` to another location, say `/opt/local`, run it like this:
```sh
SEAFILE_INSTALL_PREFIX=/opt/local ./run_tests.sh
```
================================================
FILE: autogen.sh
================================================
#!/bin/bash
# Run this to generate all the initial makefiles, etc.
: ${AUTOCONF=autoconf}
: ${AUTOHEADER=autoheader}
: ${AUTOMAKE=automake}
: ${ACLOCAL=aclocal}
if test "$(uname)" != "Darwin"; then
: ${LIBTOOLIZE=libtoolize}
else
: ${LIBTOOLIZE=glibtoolize}
fi
: ${INTLTOOLIZE=intltoolize}
: ${LIBTOOL=libtool}
srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
ORIGDIR=`pwd`
cd $srcdir
PROJECT=ccnet
TEST_TYPE=-f
FILE=net/main.c
CONFIGURE=configure.ac
DIE=0
($AUTOCONF --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "You must have autoconf installed to compile $PROJECT."
echo "Download the appropriate package for your distribution,"
echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
DIE=1
}
(grep "^AC_PROG_INTLTOOL" $srcdir/$CONFIGURE >/dev/null) && {
($INTLTOOLIZE --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "You must have \`intltoolize' installed to compile $PROJECT."
echo "Get ftp://ftp.gnome.org/pub/GNOME/stable/sources/intltool/intltool-0.22.tar.gz"
echo "(or a newer version if it is available)"
DIE=1
}
}
($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "You must have automake installed to compile $PROJECT."
echo "Get ftp://sourceware.cygnus.com/pub/automake/automake-1.7.tar.gz"
echo "(or a newer version if it is available)"
DIE=1
}
if test "$(uname)" != "Darwin"; then
(grep "^AC_PROG_LIBTOOL" $CONFIGURE >/dev/null) && {
($LIBTOOL --version) < /dev/null > /dev/null 2>&1 || {
echo
echo "**Error**: You must have \`libtool' installed to compile $PROJECT."
echo "Get ftp://ftp.gnu.org/pub/gnu/libtool-1.4.tar.gz"
echo "(or a newer version if it is available)"
DIE=1
}
}
fi
if grep "^AM_[A-Z0-9_]\{1,\}_GETTEXT" "$CONFIGURE" >/dev/null; then
if grep "sed.*POTFILES" "$CONFIGURE" >/dev/null; then
GETTEXTIZE=""
else
if grep "^AM_GLIB_GNU_GETTEXT" "$CONFIGURE" >/dev/null; then
GETTEXTIZE="glib-gettextize"
GETTEXTIZE_URL="ftp://ftp.gtk.org/pub/gtk/v2.0/glib-2.0.0.tar.gz"
else
GETTEXTIZE="gettextize"
GETTEXTIZE_URL="ftp://alpha.gnu.org/gnu/gettext-0.10.35.tar.gz"
fi
$GETTEXTIZE --version < /dev/null > /dev/null 2>&1
if test $? -ne 0; then
echo
echo "**Error**: You must have \`$GETTEXTIZE' installed to compile $PKG_NAME."
echo "Get $GETTEXTIZE_URL"
echo "(or a newer version if it is available)"
DIE=1
fi
fi
fi
if test "$DIE" -eq 1; then
exit 1
fi
dr=`dirname .`
echo processing $dr
aclocalinclude="$aclocalinclude -I m4"
if test x"$MSYSTEM" = x"MINGW32"; then
aclocalinclude="$aclocalinclude -I /mingw32/share/aclocal"
elif test "$(uname)" = "Darwin"; then
aclocalinclude="$aclocalinclude -I /opt/local/share/aclocal"
fi
echo "Creating $dr/aclocal.m4 ..."
test -r $dr/aclocal.m4 || touch $dr/aclocal.m4
echo "Running glib-gettextize... Ignore non-fatal messages."
echo "no" | glib-gettextize --force --copy
echo "Making $dr/aclocal.m4 writable ..."
test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4
echo "Running intltoolize..."
intltoolize --copy --force --automake
echo "Running $LIBTOOLIZE..."
$LIBTOOLIZE --force --copy
echo "Running $ACLOCAL $aclocalinclude ..."
$ACLOCAL $aclocalinclude
echo "Running $AUTOHEADER..."
$AUTOHEADER
echo "Running $AUTOMAKE --gnu $am_opt ..."
$AUTOMAKE --add-missing --gnu $am_opt
echo "Running $AUTOCONF ..."
$AUTOCONF
================================================
FILE: ci/install-deps.sh
================================================
#!/bin/bash
set -e -x
SCRIPT=${BASH_SOURCE[0]}
TESTS_DIR=$(dirname "${SCRIPT}")/..
SETUP_DIR=${TESTS_DIR}/ci
cd $SETUP_DIR
sudo systemctl start mysql.service
sudo apt-get update --fix-missing
sudo apt-get install -y intltool libarchive-dev libcurl4-openssl-dev libevent-dev \
libfuse-dev libglib2.0-dev libjansson-dev libmysqlclient-dev libonig-dev \
sqlite3 libsqlite3-dev libtool net-tools uuid-dev valac libargon2-dev
sudo systemctl start mysql.service
pip install -r requirements.txt
================================================
FILE: ci/requirements.txt
================================================
termcolor>=1.1.0
requests>=2.8.0
pytest>=3.3.2
backports.functools_lru_cache>=1.4
tenacity>=4.8.0
future
requests-toolbelt
================================================
FILE: ci/run.py
================================================
#!/usr/bin/env python
"""
Install dir: ~/opt/local
Data dir: /tmp/haiwen
"""
import argparse
import glob
import json
import logging
import os
import re
import sys
from os.path import abspath, basename, exists, expanduser, join
import requests
import termcolor
import site
from serverctl import ServerCtl
from utils import (
cd, chdir, debug, green, info, lru_cache, mkdirs, on_github_actions, red,
setup_logging, shell, warning
)
logger = logging.getLogger(__name__)
TOPDIR = abspath(join(os.getcwd(), '..'))
if on_github_actions():
PREFIX = expanduser('~/opt/local')
else:
PREFIX = os.environ.get('SEAFILE_INSTALL_PREFIX', '/usr/local')
INSTALLDIR = '/tmp/seafile-tests'
def num_jobs():
return int(os.environ.get('NUM_JOBS', 2))
@lru_cache()
def make_build_env():
env = dict(os.environ)
libsearpc_dir = abspath(join(TOPDIR, 'libsearpc'))
ccnet_dir = abspath(join(TOPDIR, 'ccnet-server'))
def _env_add(*a, **kw):
kw['env'] = env
return prepend_env_value(*a, **kw)
_env_add('CPPFLAGS', '-I%s' % join(PREFIX, 'include'), seperator=' ')
_env_add('LDFLAGS', '-L%s' % join(PREFIX, 'lib'), seperator=' ')
_env_add('LDFLAGS', '-L%s' % join(PREFIX, 'lib64'), seperator=' ')
_env_add('PATH', join(PREFIX, 'bin'))
py_version = '.'.join(map(str, sys.version_info[:3]))
if on_github_actions():
_env_add('PYTHONPATH', join(os.environ.get('RUNNER_TOOL_CACHE'), 'Python/{py_version}/x64/lib/python3.12/site-packages'))
_env_add('PYTHONPATH', join(PREFIX, 'lib/python3.12/site-packages'))
_env_add('PKG_CONFIG_PATH', join(PREFIX, 'lib', 'pkgconfig'))
_env_add('PKG_CONFIG_PATH', join(PREFIX, 'lib64', 'pkgconfig'))
_env_add('PKG_CONFIG_PATH', libsearpc_dir)
_env_add('PKG_CONFIG_PATH', ccnet_dir)
_env_add('LD_LIBRARY_PATH', join(PREFIX, 'lib'))
_env_add('JWT_PRIVATE_KEY', '@%ukmcl$k=9u-grs4azdljk(sn0kd!=mzc17xd7x8#!u$1x@kl')
_env_add('SEAFILE_MYSQL_DB_CCNET_DB_NAME', 'ccnet')
# Prepend the seafile-server/python to PYTHONPATH so we don't need to "make
# install" each time after editing python files.
_env_add('PYTHONPATH', join(SeafileServer().projectdir, 'python'))
for key in ('PATH', 'PKG_CONFIG_PATH', 'CPPFLAGS', 'LDFLAGS', 'PYTHONPATH'):
info('%s: %s', key, env.get(key, ''))
return env
def prepend_env_value(name, value, seperator=':', env=None):
'''append a new value to a list'''
env = env or os.environ
current_value = env.get(name, '')
new_value = value
if current_value:
new_value += seperator + current_value
env[name] = new_value
return env
@lru_cache()
def get_branch_json_file():
url = 'https://raw.githubusercontent.com/haiwen/seafile-test-deploy/master/branches.json'
return requests.get(url).json()
def get_project_branch(project, default_branch='master'):
travis_branch = os.environ.get('TRAVIS_BRANCH', 'master')
if project.name == 'seafile-server':
return travis_branch
conf = get_branch_json_file()
return conf.get(travis_branch, {}).get(project.name, default_branch)
class Project(object):
def __init__(self, name):
self.name = name
self.version = ''
@property
def url(self):
return 'https://www.github.com/haiwen/{}.git'.format(self.name)
@property
def projectdir(self):
return join(TOPDIR, self.name)
def branch(self):
return get_project_branch(self)
def clone(self):
if exists(self.name):
with cd(self.name):
shell('git fetch origin --tags')
else:
shell(
'git clone --depth=1 --branch {} {}'.
format(self.branch(), self.url)
)
@chdir
def compile_and_install(self):
cmds = [
'./autogen.sh',
'./configure --prefix={}'.format(PREFIX),
'make -j{} V=0'.format(num_jobs()),
'make install',
]
for cmd in cmds:
shell(cmd)
@chdir
def use_branch(self, branch):
shell('git checkout {}'.format(branch))
class Libsearpc(Project):
def __init__(self):
super(Libsearpc, self).__init__('libsearpc')
def branch(self):
return 'master'
class CcnetServer(Project):
def __init__(self):
super(CcnetServer, self).__init__('ccnet-server')
def branch(self):
return '7.1'
class SeafileServer(Project):
def __init__(self):
super(SeafileServer, self).__init__('seafile-server')
class Libevhtp(Project):
def __init__(self):
super(Libevhtp, self).__init__('libevhtp')
def branch(self):
return 'master'
@chdir
def compile_and_install(self):
cmds = [
'cmake -DEVHTP_DISABLE_SSL=ON -DEVHTP_BUILD_SHARED=OFF -DCMAKE_POLICY_VERSION_MINIMUM=3.5 .',
'make',
'sudo make install',
'sudo ldconfig',
]
for cmd in cmds:
shell(cmd)
class Libjwt(Project):
def __init__(self):
super(Libjwt, self).__init__('libjwt')
def branch(self):
return 'v1.13.1'
@property
def url(self):
return 'https://www.github.com/benmcollins/libjwt.git'
@chdir
def compile_and_install(self):
cmds = [
'autoreconf -i',
'./configure',
'sudo make all',
'sudo make install',
]
for cmd in cmds:
shell(cmd)
class Libhiredis(Project):
def __init__(self):
super(Libhiredis, self).__init__('hiredis')
def branch(self):
return 'v1.1.0'
@property
def url(self):
return 'https://github.com/redis/hiredis.git'
@chdir
def compile_and_install(self):
cmds = [
'sudo make',
'sudo make install',
]
for cmd in cmds:
shell(cmd)
def fetch_and_build():
libsearpc = Libsearpc()
libjwt = Libjwt()
libhiredis = Libhiredis()
libevhtp = Libevhtp()
ccnet = CcnetServer()
seafile = SeafileServer()
libsearpc.clone()
libjwt.clone()
libhiredis.clone()
libevhtp.clone()
ccnet.clone()
libsearpc.compile_and_install()
libjwt.compile_and_install()
libhiredis.compile_and_install()
libevhtp.compile_and_install()
seafile.compile_and_install()
def parse_args():
ap = argparse.ArgumentParser()
ap.add_argument('-v', '--verbose', action='store_true')
ap.add_argument('-t', '--test-only', action='store_true')
return ap.parse_args()
def main():
mkdirs(INSTALLDIR)
os.environ.update(make_build_env())
args = parse_args()
if on_github_actions() and not args.test_only:
fetch_and_build()
dbs = ('mysql',)
for db in dbs:
start_and_test_with_db(db)
def start_and_test_with_db(db):
if db == 'sqlite3':
fileservers = ('c_fileserver',)
else:
fileservers = ('go_fileserver', 'c_fileserver')
for fileserver in fileservers:
shell('rm -rf {}/*'.format(INSTALLDIR))
info('Setting up seafile server with %s database, use %s', db, fileserver)
server = ServerCtl(
TOPDIR,
SeafileServer().projectdir,
INSTALLDIR,
fileserver,
db=db,
# Use the newly built seaf-server (to avoid "make install" each time when developping locally)
seaf_server_bin=join(SeafileServer().projectdir, 'server/seaf-server')
)
server.setup()
with server.run():
info('Testing with %s database', db)
with cd(SeafileServer().projectdir):
shell('py.test', env=server.get_seaserv_envs())
if __name__ == '__main__':
os.chdir(TOPDIR)
setup_logging()
main()
================================================
FILE: ci/serverctl.py
================================================
#!/usr/bin/env python
#coding: UTF-8
import argparse
import glob
import logging
import os
import re
import sys
from collections import namedtuple
from contextlib import contextmanager
from os.path import abspath, basename, dirname, exists, join
import requests
from tenacity import TryAgain, retry, stop_after_attempt, wait_fixed
from utils import (
cd, chdir, debug, green, info, mkdirs, red, setup_logging, shell, warning
)
logger = logging.getLogger(__name__)
class ServerCtl(object):
def __init__(self, topdir, projectdir, datadir, fileserver, db='sqlite3', seaf_server_bin='seaf-server', ccnet_server_bin='ccnet-server'):
self.db = db
self.topdir = topdir
self.datadir = datadir
self.central_conf_dir = join(datadir, 'conf')
self.seafile_conf_dir = join(datadir, 'seafile-data')
self.ccnet_conf_dir = join(datadir, 'ccnet')
self.log_dir = join(datadir, 'logs')
mkdirs(self.log_dir)
self.ccnet_log = join(self.log_dir, 'ccnet.log')
self.seafile_log = join(self.log_dir, 'seafile.log')
self.fileserver_log = join(self.log_dir, 'fileserver.log')
self.ccnet_server_bin = ccnet_server_bin
self.seaf_server_bin = seaf_server_bin
self.sql_dir = join(topdir, 'seafile-server', 'scripts', 'sql')
self.ccnet_proc = None
self.seafile_proc = None
self.fileserver_proc = None
self.projectdir = projectdir
self.fileserver = fileserver
def setup(self):
if self.db == 'mysql':
create_mysql_dbs()
os.mkdir (self.central_conf_dir, 0o755)
os.mkdir (self.seafile_conf_dir, 0o755)
os.mkdir (self.ccnet_conf_dir, 0o755)
self.init_seafile()
def init_seafile(self):
seafile_conf = join(self.central_conf_dir, 'seafile.conf')
if self.fileserver == 'go_fileserver':
seafile_fileserver_conf = '''\
[fileserver]
use_go_fileserver = true
port=8082
'''
else:
seafile_fileserver_conf = '''\
[fileserver]
port=8082
'''
with open(seafile_conf, 'a+') as fp:
fp.write('\n')
fp.write(seafile_fileserver_conf)
if self.db == 'mysql':
self.add_seafile_db_conf()
else:
self.add_seafile_sqlite_db_conf()
def add_seafile_sqlite_db_conf(self):
seafile_conf = join(self.central_conf_dir, 'seafile.conf')
seafile_db_conf = '''\
[database]
'''
with open(seafile_conf, 'a+') as fp:
fp.write('\n')
fp.write(seafile_db_conf)
def add_seafile_db_conf(self):
seafile_conf = join(self.central_conf_dir, 'seafile.conf')
seafile_db_conf = '''\
[database]
type = mysql
host = 127.0.0.1
port = 3306
user = seafile
password = seafile
db_name = seafile
connection_charset = utf8
'''
with open(seafile_conf, 'a+') as fp:
fp.write('\n')
fp.write(seafile_db_conf)
@contextmanager
def run(self):
try:
self.start()
yield self
except:
self.print_logs()
raise
finally:
self.stop()
def print_logs(self):
for logfile in self.ccnet_log, self.seafile_log:
if exists(logfile):
shell(f'cat {logfile}')
@retry(wait=wait_fixed(1), stop=stop_after_attempt(10))
def wait_ccnet_ready(self):
if not exists(join(self.ccnet_conf_dir, 'ccnet-rpc.sock')):
raise TryAgain
def start(self):
logger.info('Starting to create ccnet and seafile db tables')
self.create_database_tables()
logger.info('Starting seafile server')
self.start_seafile()
self.start_fileserver()
def create_database_tables(self):
if self.db == 'mysql':
ccnet_sql_path = join(self.sql_dir, 'mysql', 'ccnet.sql')
seafile_sql_path = join(self.sql_dir, 'mysql', 'seafile.sql')
sql = f'USE ccnet; source {ccnet_sql_path}; USE seafile; source {seafile_sql_path};'.encode()
shell('sudo mysql -u root -proot', inputdata=sql, wait=False)
else:
config_sql_path = join(self.sql_dir, 'sqlite', 'config.sql')
groupmgr_sql_path = join(self.sql_dir, 'sqlite', 'groupmgr.sql')
org_sql_path = join(self.sql_dir, 'sqlite', 'org.sql')
user_sql_path = join(self.sql_dir, 'sqlite', 'user.sql')
seafile_sql_path = join(self.sql_dir, 'sqlite', 'seafile.sql')
misc_dir = join(self.ccnet_conf_dir, 'misc')
os.mkdir (misc_dir, 0o755)
groupmgr_dir = join(self.ccnet_conf_dir, 'GroupMgr')
os.mkdir (groupmgr_dir, 0o755)
orgmgr_dir = join(self.ccnet_conf_dir, 'OrgMgr')
os.mkdir (orgmgr_dir, 0o755)
usermgr_dir = join(self.ccnet_conf_dir, 'PeerMgr')
os.mkdir (usermgr_dir, 0o755)
config_db_path = join(misc_dir, 'config.db')
groupmgr_db_path = join(groupmgr_dir, 'groupmgr.db')
orgmgr_db_path = join(orgmgr_dir, 'orgmgr.db')
usermgr_db_path = join(usermgr_dir, 'usermgr.db')
seafile_db_path = join(self.seafile_conf_dir, 'seafile.db')
sql = f'.read {config_sql_path}'.encode()
shell('sqlite3 ' + config_db_path, inputdata=sql, wait=False)
sql = f'.read {groupmgr_sql_path}'.encode()
shell('sqlite3 ' + groupmgr_db_path, inputdata=sql, wait=False)
sql = f'.read {org_sql_path}'.encode()
shell('sqlite3 ' + orgmgr_db_path, inputdata=sql, wait=False)
sql = f'.read {user_sql_path}'.encode()
shell('sqlite3 ' + usermgr_db_path, inputdata=sql, wait=False)
sql = f'.read {seafile_sql_path}'.encode()
shell('sqlite3 ' + seafile_db_path, inputdata=sql, wait=False)
def start_ccnet(self):
cmd = [
self.ccnet_server_bin,
"-F",
self.central_conf_dir,
"-c",
self.ccnet_conf_dir,
"-f",
self.ccnet_log,
]
self.ccnet_proc = shell(cmd, wait=False)
def start_seafile(self):
cmd = [
self.seaf_server_bin,
"-F",
self.central_conf_dir,
"-c",
self.ccnet_conf_dir,
"-d",
self.seafile_conf_dir,
"-l",
self.seafile_log,
"-f",
]
self.seafile_proc = shell(cmd, wait=False)
def start_fileserver(self):
cmd = [
"./fileserver",
"-F",
self.central_conf_dir,
"-d",
self.seafile_conf_dir,
"-l",
self.fileserver_log,
]
fileserver_path = join(self.projectdir, 'fileserver')
with cd(fileserver_path):
shell("go build")
self.fileserver_proc = shell(cmd, wait=False)
def stop(self):
if self.ccnet_proc:
logger.info('Stopping ccnet server')
self.ccnet_proc.kill()
if self.seafile_proc:
logger.info('Stopping seafile server')
self.seafile_proc.kill()
if self.fileserver_proc:
logger.info('Stopping go fileserver')
self.fileserver_proc.kill()
if self.db == 'mysql':
del_mysql_dbs()
def get_seaserv_envs(self):
envs = dict(os.environ)
envs.update({
'SEAFILE_CENTRAL_CONF_DIR': self.central_conf_dir,
'CCNET_CONF_DIR': self.ccnet_conf_dir,
'SEAFILE_CONF_DIR': self.seafile_conf_dir,
'SEAFILE_MYSQL_DB_CCNET_DB_NAME': 'ccnet',
})
return envs
def create_mysql_dbs():
sql = b'''\
create database `ccnet` character set = 'utf8';
create database `seafile` character set = 'utf8';
create user 'seafile'@'localhost' identified by 'seafile';
GRANT ALL PRIVILEGES ON `ccnet`.* to `seafile`@localhost;
GRANT ALL PRIVILEGES ON `seafile`.* to `seafile`@localhost;
'''
shell('sudo mysql -u root -proot', inputdata=sql)
def del_mysql_dbs():
sql = b'''\
drop database `ccnet`;
drop database `seafile`;
drop user 'seafile'@'localhost';
'''
shell('sudo mysql -u root -proot', inputdata=sql)
================================================
FILE: ci/utils.py
================================================
#coding: UTF-8
import logging
import os
import re
import sys
from contextlib import contextmanager
from os.path import abspath, basename, exists, expanduser, join
from subprocess import PIPE, CalledProcessError, Popen
import requests
import termcolor
try:
from functools import lru_cache
except ImportError:
from backports.functools_lru_cache import lru_cache
logger = logging.getLogger(__name__)
def _color(s, color):
return s if not os.isatty(sys.stdout.fileno()) \
else termcolor.colored(str(s), color)
def green(s):
return _color(s, 'green')
def red(s):
return _color(s, 'red')
def debug(fmt, *a):
logger.debug(green(fmt), *a)
def info(fmt, *a):
logger.info(green(fmt), *a)
def warning(fmt, *a):
logger.warn(red(fmt), *a)
def shell(cmd, inputdata=None, wait=True, **kw):
info('calling "%s" in %s', cmd, kw.get('cwd', os.getcwd()))
kw['shell'] = not isinstance(cmd, list)
kw['stdin'] = PIPE if inputdata else None
p = Popen(cmd, **kw)
if inputdata:
p.communicate(inputdata)
if wait:
p.wait()
if p.returncode:
raise CalledProcessError(p.returncode, cmd)
else:
return p
@contextmanager
def cd(path):
olddir = os.getcwd()
os.chdir(path)
try:
yield
finally:
os.chdir(olddir)
def chdir(func):
def wrapped(self, *w, **kw):
with cd(self.projectdir):
return func(self, *w, **kw)
return wrapped
def setup_logging():
kw = {
'format': '[%(asctime)s][%(module)s]: %(message)s',
'datefmt': '%m/%d/%Y %H:%M:%S',
'level': logging.DEBUG,
'stream': sys.stdout,
}
logging.basicConfig(**kw)
logging.getLogger('requests.packages.urllib3.connectionpool'
).setLevel(logging.WARNING)
def mkdirs(*paths):
for path in paths:
if not exists(path):
os.mkdir(path)
def on_github_actions():
return 'GITHUB_ACTIONS' in os.environ
@contextmanager
def cd(path):
path = expanduser(path)
olddir = os.getcwd()
os.chdir(path)
try:
yield
finally:
os.chdir(olddir)
================================================
FILE: common/Makefile.am
================================================
SUBDIRS = cdc
proc_headers = \
$(addprefix processors/, \
objecttx-common.h)
noinst_HEADERS = \
diff-simple.h \
seafile-crypt.h \
password-hash.h \
common.h \
branch-mgr.h \
fs-mgr.h \
block-mgr.h \
commit-mgr.h \
log.h \
object-list.h \
vc-common.h \
seaf-utils.h \
obj-store.h \
obj-backend.h \
block-backend.h \
block.h \
mq-mgr.h \
seaf-db.h \
config-mgr.h \
merge-new.h \
block-tx-utils.h \
sync-repo-common.h \
$(proc_headers)
================================================
FILE: common/block-backend-fs.c
================================================
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x500
#endif
#include "common.h"
#include "utils.h"
#include "log.h"
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include "block-backend.h"
#include "obj-store.h"
struct _BHandle {
char *store_id;
int version;
char block_id[41];
int fd;
int rw_type;
char *tmp_file;
};
typedef struct {
char *block_dir;
int block_dir_len;
char *tmp_dir;
int tmp_dir_len;
} FsPriv;
static char *
get_block_path (BlockBackend *bend,
const char *block_sha1,
char path[],
const char *store_id,
int version);
static int
open_tmp_file (BlockBackend *bend,
const char *basename,
char **path);
static BHandle *
block_backend_fs_open_block (BlockBackend *bend,
const char *store_id,
int version,
const char *block_id,
int rw_type)
{
BHandle *handle;
int fd = -1;
char *tmp_file;
g_return_val_if_fail (block_id != NULL, NULL);
g_return_val_if_fail (strlen(block_id) == 40, NULL);
g_return_val_if_fail (rw_type == BLOCK_READ || rw_type == BLOCK_WRITE, NULL);
if (rw_type == BLOCK_READ) {
char path[SEAF_PATH_MAX];
get_block_path (bend, block_id, path, store_id, version);
fd = g_open (path, O_RDONLY | O_BINARY, 0);
if (fd < 0) {
ccnet_warning ("[block bend] failed to open block %s for read: %s\n",
block_id, strerror(errno));
return NULL;
}
} else {
fd = open_tmp_file (bend, block_id, &tmp_file);
if (fd < 0) {
ccnet_warning ("[block bend] failed to open block %s for write: %s\n",
block_id, strerror(errno));
return NULL;
}
}
handle = g_new0(BHandle, 1);
handle->fd = fd;
memcpy (handle->block_id, block_id, 41);
handle->rw_type = rw_type;
if (rw_type == BLOCK_WRITE)
handle->tmp_file = tmp_file;
if (store_id)
handle->store_id = g_strdup(store_id);
handle->version = version;
return handle;
}
static int
block_backend_fs_read_block (BlockBackend *bend,
BHandle *handle,
void *buf, int len)
{
int ret;
ret = readn (handle->fd, buf, len);
if (ret < 0)
seaf_warning ("Failed to read block %s:%s: %s.\n",
handle->store_id, handle->block_id, strerror (errno));
return ret;
}
static int
block_backend_fs_write_block (BlockBackend *bend,
BHandle *handle,
const void *buf, int len)
{
int ret;
ret = writen (handle->fd, buf, len);
if (ret < 0)
seaf_warning ("Failed to write block %s:%s: %s.\n",
handle->store_id, handle->block_id, strerror (errno));
return ret;
}
static int
block_backend_fs_close_block (BlockBackend *bend,
BHandle *handle)
{
int ret;
ret = close (handle->fd);
return ret;
}
static void
block_backend_fs_block_handle_free (BlockBackend *bend,
BHandle *handle)
{
if (handle->rw_type == BLOCK_WRITE) {
/* make sure the tmp file is removed even on failure. */
g_unlink (handle->tmp_file);
g_free (handle->tmp_file);
}
g_free (handle->store_id);
g_free (handle);
}
static int
create_parent_path (const char *path)
{
char *dir = g_path_get_dirname (path);
if (!dir)
return -1;
if (g_file_test (dir, G_FILE_TEST_EXISTS)) {
g_free (dir);
return 0;
}
if (g_mkdir_with_parents (dir, 0777) < 0) {
seaf_warning ("Failed to create object parent path: %s.\n", dir);
g_free (dir);
return -1;
}
g_free (dir);
return 0;
}
static int
block_backend_fs_commit_block (BlockBackend *bend,
BHandle *handle)
{
char path[SEAF_PATH_MAX];
g_return_val_if_fail (handle->rw_type == BLOCK_WRITE, -1);
get_block_path (bend, handle->block_id, path, handle->store_id, handle->version);
if (create_parent_path (path) < 0) {
seaf_warning ("Failed to create path for block %s:%s.\n",
handle->store_id, handle->block_id);
return -1;
}
if (g_rename (handle->tmp_file, path) < 0) {
seaf_warning ("[block bend] failed to commit block %s:%s: %s\n",
handle->store_id, handle->block_id, strerror(errno));
return -1;
}
return 0;
}
static gboolean
block_backend_fs_block_exists (BlockBackend *bend,
const char *store_id,
int version,
const char *block_sha1)
{
char block_path[SEAF_PATH_MAX];
get_block_path (bend, block_sha1, block_path, store_id, version);
if (g_access (block_path, F_OK) == 0)
return TRUE;
else
return FALSE;
}
static int
block_backend_fs_remove_block (BlockBackend *bend,
const char *store_id,
int version,
const char *block_id)
{
char path[SEAF_PATH_MAX];
get_block_path (bend, block_id, path, store_id, version);
return g_unlink (path);
}
static BMetadata *
block_backend_fs_stat_block (BlockBackend *bend,
const char *store_id,
int version,
const char *block_id)
{
char path[SEAF_PATH_MAX];
SeafStat st;
BMetadata *block_md;
get_block_path (bend, block_id, path, store_id, version);
if (seaf_stat (path, &st) < 0) {
seaf_warning ("[block bend] Failed to stat block %s:%s at %s: %s.\n",
store_id, block_id, path, strerror(errno));
return NULL;
}
block_md = g_new0(BMetadata, 1);
memcpy (block_md->id, block_id, 40);
block_md->size = (uint32_t) st.st_size;
return block_md;
}
static BMetadata *
block_backend_fs_stat_block_by_handle (BlockBackend *bend,
BHandle *handle)
{
SeafStat st;
BMetadata *block_md;
if (seaf_fstat (handle->fd, &st) < 0) {
seaf_warning ("[block bend] Failed to stat block %s:%s.\n",
handle->store_id, handle->block_id);
return NULL;
}
block_md = g_new0(BMetadata, 1);
memcpy (block_md->id, handle->block_id, 40);
block_md->size = (uint32_t) st.st_size;
return block_md;
}
static int
block_backend_fs_foreach_block (BlockBackend *bend,
const char *store_id,
int version,
SeafBlockFunc process,
void *user_data)
{
FsPriv *priv = bend->be_priv;
char *block_dir = NULL;
int dir_len;
GDir *dir1 = NULL, *dir2;
const char *dname1, *dname2;
char block_id[128];
char path[SEAF_PATH_MAX], *pos;
int ret = 0;
#if defined MIGRATION
if (version > 0)
block_dir = g_build_filename (priv->block_dir, store_id, NULL);
#else
block_dir = g_build_filename (priv->block_dir, store_id, NULL);
#endif
dir_len = strlen (block_dir);
dir1 = g_dir_open (block_dir, 0, NULL);
if (!dir1) {
goto out;
}
memcpy (path, block_dir, dir_len);
pos = path + dir_len;
while ((dname1 = g_dir_read_name(dir1)) != NULL) {
snprintf (pos, sizeof(path) - dir_len, "/%s", dname1);
dir2 = g_dir_open (path, 0, NULL);
if (!dir2) {
seaf_warning ("Failed to open block dir %s.\n", path);
continue;
}
while ((dname2 = g_dir_read_name(dir2)) != NULL) {
snprintf (block_id, sizeof(block_id), "%s%s", dname1, dname2);
if (!process (store_id, version, block_id, user_data)) {
g_dir_close (dir2);
goto out;
}
}
g_dir_close (dir2);
}
out:
if (dir1)
g_dir_close (dir1);
g_free (block_dir);
return ret;
}
static int
block_backend_fs_copy (BlockBackend *bend,
const char *src_store_id,
int src_version,
const char *dst_store_id,
int dst_version,
const char *block_id)
{
char src_path[SEAF_PATH_MAX];
char dst_path[SEAF_PATH_MAX];
get_block_path (bend, block_id, src_path, src_store_id, src_version);
get_block_path (bend, block_id, dst_path, dst_store_id, dst_version);
if (g_file_test (dst_path, G_FILE_TEST_EXISTS))
return 0;
if (create_parent_path (dst_path) < 0) {
seaf_warning ("Failed to create dst path %s for block %s.\n",
dst_path, block_id);
return -1;
}
#ifdef WIN32
if (!CreateHardLink (dst_path, src_path, NULL)) {
seaf_warning ("Failed to link %s to %s: %lu.\n",
src_path, dst_path, GetLastError());
return -1;
}
return 0;
#else
int ret = link (src_path, dst_path);
if (ret < 0 && errno != EEXIST) {
seaf_warning ("Failed to link %s to %s: %s.\n",
src_path, dst_path, strerror(errno));
return -1;
}
return ret;
#endif
}
static int
block_backend_fs_remove_store (BlockBackend *bend, const char *store_id)
{
FsPriv *priv = bend->be_priv;
char *block_dir = NULL;
GDir *dir1, *dir2;
const char *dname1, *dname2;
char *path1, *path2;
block_dir = g_build_filename (priv->block_dir, store_id, NULL);
dir1 = g_dir_open (block_dir, 0, NULL);
if (!dir1) {
g_free (block_dir);
return 0;
}
while ((dname1 = g_dir_read_name(dir1)) != NULL) {
path1 = g_build_filename (block_dir, dname1, NULL);
dir2 = g_dir_open (path1, 0, NULL);
if (!dir2) {
seaf_warning ("Failed to open block dir %s.\n", path1);
g_dir_close (dir1);
g_free (path1);
g_free (block_dir);
return -1;
}
while ((dname2 = g_dir_read_name(dir2)) != NULL) {
path2 = g_build_filename (path1, dname2, NULL);
g_unlink (path2);
g_free (path2);
}
g_dir_close (dir2);
g_rmdir (path1);
g_free (path1);
}
g_dir_close (dir1);
g_rmdir (block_dir);
g_free (block_dir);
return 0;
}
static char *
get_block_path (BlockBackend *bend,
const char *block_sha1,
char path[],
const char *store_id,
int version)
{
FsPriv *priv = bend->be_priv;
char *pos = path;
int n;
#if defined MIGRATION
if (version > 0) {
n = snprintf (path, SEAF_PATH_MAX, "%s/%s/", priv->block_dir, store_id);
pos += n;
} else
#else
n = snprintf (path, SEAF_PATH_MAX, "%s/%s/", priv->block_dir, store_id);
pos += n;
#endif
memcpy (pos, block_sha1, 2);
pos[2] = '/';
pos += 3;
memcpy (pos, block_sha1 + 2, 41 - 2);
return path;
}
static int
open_tmp_file (BlockBackend *bend,
const char *basename,
char **path)
{
FsPriv *priv = bend->be_priv;
int fd;
*path = g_strdup_printf ("%s/%s.XXXXXX", priv->tmp_dir, basename);
fd = g_mkstemp (*path);
if (fd < 0)
g_free (*path);
return fd;
}
BlockBackend *
block_backend_fs_new (const char *seaf_dir, const char *tmp_dir)
{
BlockBackend *bend;
FsPriv *priv;
bend = g_new0(BlockBackend, 1);
priv = g_new0(FsPriv, 1);
bend->be_priv = priv;
priv->block_dir = g_build_filename (seaf_dir, "storage", "blocks", NULL);
priv->block_dir_len = strlen (priv->block_dir);
priv->tmp_dir = g_strdup (tmp_dir);
priv->tmp_dir_len = strlen (tmp_dir);
if (g_mkdir_with_parents (priv->block_dir, 0777) < 0) {
seaf_warning ("Block dir %s does not exist and"
" is unable to create\n", priv->block_dir);
goto onerror;
}
if (g_mkdir_with_parents (tmp_dir, 0777) < 0) {
seaf_warning ("Blocks tmp dir %s does not exist and"
" is unable to create\n", tmp_dir);
goto onerror;
}
bend->open_block = block_backend_fs_open_block;
bend->read_block = block_backend_fs_read_block;
bend->write_block = block_backend_fs_write_block;
bend->commit_block = block_backend_fs_commit_block;
bend->close_block = block_backend_fs_close_block;
bend->exists = block_backend_fs_block_exists;
bend->remove_block = block_backend_fs_remove_block;
bend->stat_block = block_backend_fs_stat_block;
bend->stat_block_by_handle = block_backend_fs_stat_block_by_handle;
bend->block_handle_free = block_backend_fs_block_handle_free;
bend->foreach_block = block_backend_fs_foreach_block;
bend->remove_store = block_backend_fs_remove_store;
bend->copy = block_backend_fs_copy;
return bend;
onerror:
g_free (bend->be_priv);
g_free (bend);
return NULL;
}
================================================
FILE: common/block-backend.c
================================================
#include "common.h"
#include "log.h"
#include "block-backend.h"
extern BlockBackend *
block_backend_fs_new (const char *block_dir, const char *tmp_dir);
BlockBackend*
load_filesystem_block_backend(GKeyFile *config)
{
BlockBackend *bend;
char *tmp_dir;
char *block_dir;
block_dir = g_key_file_get_string (config, "block_backend", "block_dir", NULL);
if (!block_dir) {
seaf_warning ("Block dir not set in config.\n");
return NULL;
}
tmp_dir = g_key_file_get_string (config, "block_backend", "tmp_dir", NULL);
if (!tmp_dir) {
seaf_warning ("Block tmp dir not set in config.\n");
return NULL;
}
bend = block_backend_fs_new (block_dir, tmp_dir);
g_free (block_dir);
g_free (tmp_dir);
return bend;
}
BlockBackend*
load_block_backend (GKeyFile *config)
{
char *backend;
BlockBackend *bend;
backend = g_key_file_get_string (config, "block_backend", "name", NULL);
if (!backend) {
return NULL;
}
if (strcmp(backend, "filesystem") == 0) {
bend = load_filesystem_block_backend(config);
g_free (backend);
return bend;
}
seaf_warning ("Unknown backend\n");
return NULL;
}
================================================
FILE: common/block-backend.h
================================================
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
#ifndef BLOCK_BACKEND_H
#define BLOCK_BACKEND_H
#include "block.h"
typedef struct BlockBackend BlockBackend;
struct BlockBackend {
BHandle* (*open_block) (BlockBackend *bend,
const char *store_id, int version,
const char *block_id, int rw_type);
int (*read_block) (BlockBackend *bend, BHandle *handle, void *buf, int len);
int (*write_block) (BlockBackend *bend, BHandle *handle, const void *buf, int len);
int (*commit_block) (BlockBackend *bend, BHandle *handle);
int (*close_block) (BlockBackend *bend, BHandle *handle);
int (*exists) (BlockBackend *bend,
const char *store_id, int version,
const char *block_id);
int (*remove_block) (BlockBackend *bend,
const char *store_id, int version,
const char *block_id);
BMetadata* (*stat_block) (BlockBackend *bend,
const char *store_id, int version,
const char *block_id);
BMetadata* (*stat_block_by_handle) (BlockBackend *bend, BHandle *handle);
void (*block_handle_free) (BlockBackend *bend, BHandle *handle);
int (*foreach_block) (BlockBackend *bend,
const char *store_id,
int version,
SeafBlockFunc process,
void *user_data);
int (*copy) (BlockBackend *bend,
const char *src_store_id,
int src_version,
const char *dst_store_id,
int dst_version,
const char *block_id);
/* Only valid for version 1 repo. Remove all blocks for the repo. */
int (*remove_store) (BlockBackend *bend,
const char *store_id);
void* be_priv; /* backend private field */
};
BlockBackend* load_block_backend (GKeyFile *config);
#endif
================================================
FILE: common/block-mgr.c
================================================
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
#include "common.h"
#include "seafile-session.h"
#include "utils.h"
#include "seaf-utils.h"
#include "block-mgr.h"
#include "log.h"
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <dirent.h>
#include <glib/gstdio.h>
#include "block-backend.h"
#define SEAF_BLOCK_DIR "blocks"
extern BlockBackend *
block_backend_fs_new (const char *block_dir, const char *tmp_dir);
SeafBlockManager *
seaf_block_manager_new (struct _SeafileSession *seaf,
const char *seaf_dir)
{
SeafBlockManager *mgr;
mgr = g_new0 (SeafBlockManager, 1);
mgr->seaf = seaf;
mgr->backend = block_backend_fs_new (seaf_dir, seaf->tmp_file_dir);
if (!mgr->backend) {
seaf_warning ("[Block mgr] Failed to load backend.\n");
goto onerror;
}
return mgr;
onerror:
g_free (mgr);
return NULL;
}
int
seaf_block_manager_init (SeafBlockManager *mgr)
{
return 0;
}
BlockHandle *
seaf_block_manager_open_block (SeafBlockManager *mgr,
const char *store_id,
int version,
const char *block_id,
int rw_type)
{
if (!store_id || !is_uuid_valid(store_id) ||
!block_id || !is_object_id_valid(block_id))
return NULL;
return mgr->backend->open_block (mgr->backend,
store_id, version,
block_id, rw_type);
}
int
seaf_block_manager_read_block (SeafBlockManager *mgr,
BlockHandle *handle,
void *buf, int len)
{
return mgr->backend->read_block (mgr->backend, handle, buf, len);
}
int
seaf_block_manager_write_block (SeafBlockManager *mgr,
BlockHandle *handle,
const void *buf, int len)
{
return mgr->backend->write_block (mgr->backend, handle, buf, len);
}
int
seaf_block_manager_close_block (SeafBlockManager *mgr,
BlockHandle *handle)
{
return mgr->backend->close_block (mgr->backend, handle);
}
void
seaf_block_manager_block_handle_free (SeafBlockManager *mgr,
BlockHandle *handle)
{
return mgr->backend->block_handle_free (mgr->backend, handle);
}
int
seaf_block_manager_commit_block (SeafBlockManager *mgr,
BlockHandle *handle)
{
return mgr->backend->commit_block (mgr->backend, handle);
}
gboolean seaf_block_manager_block_exists (SeafBlockManager *mgr,
const char *store_id,
int version,
const char *block_id)
{
if (!store_id || !is_uuid_valid(store_id) ||
!block_id || !is_object_id_valid(block_id))
return FALSE;
return mgr->backend->exists (mgr->backend, store_id, version, block_id);
}
int
seaf_block_manager_remove_block (SeafBlockManager *mgr,
const char *store_id,
int version,
const char *block_id)
{
if (!store_id || !is_uuid_valid(store_id) ||
!block_id || !is_object_id_valid(block_id))
return -1;
return mgr->backend->remove_block (mgr->backend, store_id, version, block_id);
}
BlockMetadata *
seaf_block_manager_stat_block (SeafBlockManager *mgr,
const char *store_id,
int version,
const char *block_id)
{
if (!store_id || !is_uuid_valid(store_id) ||
!block_id || !is_object_id_valid(block_id))
return NULL;
return mgr->backend->stat_block (mgr->backend, store_id, version, block_id);
}
BlockMetadata *
seaf_block_manager_stat_block_by_handle (SeafBlockManager *mgr,
BlockHandle *handle)
{
return mgr->backend->stat_block_by_handle (mgr->backend, handle);
}
int
seaf_block_manager_foreach_block (SeafBlockManager *mgr,
const char *store_id,
int version,
SeafBlockFunc process,
void *user_data)
{
return mgr->backend->foreach_block (mgr->backend,
store_id, version,
process, user_data);
}
int
seaf_block_manager_copy_block (SeafBlockManager *mgr,
const char *src_store_id,
int src_version,
const char *dst_store_id,
int dst_version,
const char *block_id)
{
if (strcmp (block_id, EMPTY_SHA1) == 0)
return 0;
if (seaf_block_manager_block_exists (mgr, dst_store_id, dst_version, block_id)) {
return 0;
}
return mgr->backend->copy (mgr->backend,
src_store_id,
src_version,
dst_store_id,
dst_version,
block_id);
}
static gboolean
get_block_number (const char *store_id,
int version,
const char *block_id,
void *data)
{
guint64 *n_blocks = data;
++(*n_blocks);
return TRUE;
}
guint64
seaf_block_manager_get_block_number (SeafBlockManager *mgr,
const char *store_id,
int version)
{
guint64 n_blocks = 0;
seaf_block_manager_foreach_block (mgr, store_id, version,
get_block_number, &n_blocks);
return n_blocks;
}
gboolean
seaf_block_manager_verify_block (SeafBlockManager *mgr,
const char *store_id,
int version,
const char *block_id,
gboolean *io_error)
{
BlockHandle *h;
char buf[10240];
int n;
SHA_CTX ctx;
guint8 sha1[20];
char check_id[41];
h = seaf_block_manager_open_block (mgr,
store_id, version,
block_id, BLOCK_READ);
if (!h) {
seaf_warning ("Failed to open block %s:%.8s.\n", store_id, block_id);
*io_error = TRUE;
return FALSE;
}
SHA1_Init (&ctx);
while (1) {
n = seaf_block_manager_read_block (mgr, h, buf, sizeof(buf));
if (n < 0) {
seaf_warning ("Failed to read block %s:%.8s.\n", store_id, block_id);
*io_error = TRUE;
return FALSE;
}
if (n == 0)
break;
SHA1_Update (&ctx, buf, n);
}
seaf_block_manager_close_block (mgr, h);
seaf_block_manager_block_handle_free (mgr, h);
SHA1_Final (sha1, &ctx);
rawdata_to_hex (sha1, check_id, 20);
if (strcmp (check_id, block_id) == 0)
return TRUE;
else
return FALSE;
}
int
seaf_block_manager_remove_store (SeafBlockManager *mgr,
const char *store_id)
{
return mgr->backend->remove_store (mgr->backend, store_id);
}
================================================
FILE: common/block-mgr.h
================================================
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
#ifndef SEAF_BLOCK_MGR_H
#define SEAF_BLOCK_MGR_H
#include <glib.h>
#include <glib-object.h>
#include <stdint.h>
#include "block.h"
struct _SeafileSession;
typedef struct _SeafBlockManager SeafBlockManager;
struct _SeafBlockManager {
struct _SeafileSession *seaf;
struct BlockBackend *backend;
};
SeafBlockManager *
seaf_block_manager_new (struct _SeafileSession *seaf,
const char *seaf_dir);
/*
* Open a block for read or write.
*
* @store_id: id for the block store
* @version: data format version for the repo
* @block_id: ID of block.
* @rw_type: BLOCK_READ or BLOCK_WRITE.
* Returns: A handle for the block.
*/
BlockHandle *
seaf_block_manager_open_block (SeafBlockManager *mgr,
const char *store_id,
int version,
const char *block_id,
int rw_type);
/*
* Read data from a block.
* The semantics is similar to readn.
*
* @handle: Hanlde returned by seaf_block_manager_open_block().
* @buf: Data wuold be copied into this buf.
* @len: At most @len bytes would be read.
*
* Returns: the bytes read.
*/
int
seaf_block_manager_read_block (SeafBlockManager *mgr,
BlockHandle *handle,
void *buf, int len);
/*
* Write data to a block.
* The semantics is similar to writen.
*
* @handle: Hanlde returned by seaf_block_manager_open_block().
* @buf: Data to be written to the block.
* @len: At most @len bytes would be written.
*
* Returns: the bytes written.
*/
int
seaf_block_manager_write_block (SeafBlockManager *mgr,
BlockHandle *handle,
const void *buf, int len);
/*
* Commit a block to storage.
* The block must be opened for write.
*
* @handle: Hanlde returned by seaf_block_manager_open_block().
*
* Returns: 0 on success, -1 on error.
*/
int
seaf_block_manager_commit_block (SeafBlockManager *mgr,
BlockHandle *handle);
/*
* Close an open block.
*
* @handle: Hanlde returned by seaf_block_manager_open_block().
*
* Returns: 0 on success, -1 on error.
*/
int
seaf_block_manager_close_block (SeafBlockManager *mgr,
BlockHandle *handle);
void
seaf_block_manager_block_handle_free (SeafBlockManager *mgr,
BlockHandle *handle);
gboolean
seaf_block_manager_block_exists (SeafBlockManager *mgr,
const char *store_id,
int version,
const char *block_id);
int
seaf_block_manager_remove_block (SeafBlockManager *mgr,
const char *store_id,
int version,
const char *block_id);
BlockMetadata *
seaf_block_manager_stat_block (SeafBlockManager *mgr,
const char *store_id,
int version,
const char *block_id);
BlockMetadata *
seaf_block_manager_stat_block_by_handle (SeafBlockManager *mgr,
BlockHandle *handle);
int
seaf_block_manager_foreach_block (SeafBlockManager *mgr,
const char *store_id,
int version,
SeafBlockFunc process,
void *user_data);
int
seaf_block_manager_copy_block (SeafBlockManager *mgr,
const char *src_store_id,
int src_version,
const char *dst_store_id,
int dst_version,
const char *block_id);
/* Remove all blocks for a repo. Only valid for version 1 repo. */
int
seaf_block_manager_remove_store (SeafBlockManager *mgr,
const char *store_id);
guint64
seaf_block_manager_get_block_number (SeafBlockManager *mgr,
const char *store_id,
int version);
gboolean
seaf_block_manager_verify_block (SeafBlockManager *mgr,
const char *store_id,
int version,
const char *block_id,
gboolean *io_error);
#endif
================================================
FILE: common/block-tx-utils.c
================================================
#include "common.h"
#define DEBUG_FLAG SEAFILE_DEBUG_TRANSFER
#include "log.h"
#include "utils.h"
#include "block-tx-utils.h"
/* Utility functions for block transfer protocol. */
/* Encryption related functions. */
void
blocktx_generate_encrypt_key (unsigned char *session_key, int sk_len,
unsigned char *key, unsigned char *iv)
{
EVP_BytesToKey (EVP_aes_256_cbc(), /* cipher mode */
EVP_sha1(), /* message digest */
NULL, /* salt */
session_key,
sk_len,
3, /* iteration times */
key, /* the derived key */
iv); /* IV, initial vector */
}
int
blocktx_encrypt_init (EVP_CIPHER_CTX **ctx,
const unsigned char *key,
const unsigned char *iv)
{
int ret;
/* Prepare CTX for encryption. */
*ctx = EVP_CIPHER_CTX_new ();
ret = EVP_EncryptInit_ex (*ctx,
EVP_aes_256_cbc(), /* cipher mode */
NULL, /* engine, NULL for default */
key, /* derived key */
iv); /* initial vector */
if (ret == 0)
return -1;
return 0;
}
int
blocktx_decrypt_init (EVP_CIPHER_CTX **ctx,
const unsigned char *key,
const unsigned char *iv)
{
int ret;
/* Prepare CTX for decryption. */
*ctx = EVP_CIPHER_CTX_new();
ret = EVP_DecryptInit_ex (*ctx,
EVP_aes_256_cbc(), /* cipher mode */
NULL, /* engine, NULL for default */
key, /* derived key */
iv); /* initial vector */
if (ret == 0)
return -1;
return 0;
}
/* Sending frame */
int
send_encrypted_data_frame_begin (evutil_socket_t data_fd,
int frame_len)
{
/* Compute data size after encryption.
* Block size is 16 bytes and AES always add one padding block.
*/
int enc_frame_len;
enc_frame_len = ((frame_len >> 4) + 1) << 4;
enc_frame_len = htonl (enc_frame_len);
if (sendn (data_fd, &enc_frame_len, sizeof(int)) < 0) {
seaf_warning ("Failed to send frame length: %s.\n",
evutil_socket_error_to_string(evutil_socket_geterror(data_fd)));
return -1;
}
return 0;
}
int
send_encrypted_data (EVP_CIPHER_CTX *ctx,
evutil_socket_t data_fd,
const void *buf, int len)
{
char out_buf[len + ENC_BLOCK_SIZE];
int out_len;
if (EVP_EncryptUpdate (ctx,
(unsigned char *)out_buf, &out_len,
(unsigned char *)buf, len) == 0) {
seaf_warning ("Failed to encrypt data.\n");
return -1;
}
if (sendn (data_fd, out_buf, out_len) < 0) {
seaf_warning ("Failed to write data: %s.\n",
evutil_socket_error_to_string(evutil_socket_geterror(data_fd)));
return -1;
}
return 0;
}
int
send_encrypted_data_frame_end (EVP_CIPHER_CTX *ctx,
evutil_socket_t data_fd)
{
char out_buf[ENC_BLOCK_SIZE];
int out_len;
if (EVP_EncryptFinal_ex (ctx, (unsigned char *)out_buf, &out_len) == 0) {
seaf_warning ("Failed to encrypt data.\n");
return -1;
}
if (sendn (data_fd, out_buf, out_len) < 0) {
seaf_warning ("Failed to write data: %s.\n",
evutil_socket_error_to_string(evutil_socket_geterror(data_fd)));
return -1;
}
return 0;
}
/* Receiving frame */
static int
handle_frame_content (struct evbuffer *buf, FrameParser *parser)
{
char *frame;
EVP_CIPHER_CTX *ctx;
char *out;
int outlen, outlen2;
int ret = 0;
struct evbuffer *input = buf;
if (evbuffer_get_length (input) < parser->enc_frame_len)
return 0;
if (parser->version == 1)
blocktx_decrypt_init (&ctx, parser->key, parser->iv);
else if (parser->version == 2)
blocktx_decrypt_init (&ctx, parser->key_v2, parser->iv_v2);
frame = g_malloc (parser->enc_frame_len);
out = g_malloc (parser->enc_frame_len + ENC_BLOCK_SIZE);
evbuffer_remove (input, frame, parser->enc_frame_len);
if (EVP_DecryptUpdate (ctx,
(unsigned char *)out, &outlen,
(unsigned char *)frame,
parser->enc_frame_len) == 0) {
seaf_warning ("Failed to decrypt frame content.\n");
ret = -1;
goto out;
}
if (EVP_DecryptFinal_ex (ctx, (unsigned char *)(out + outlen), &outlen2) == 0)
{
seaf_warning ("Failed to decrypt frame content.\n");
ret = -1;
goto out;
}
ret = parser->content_cb (out, outlen + outlen2, parser->cbarg);
out:
g_free (frame);
g_free (out);
parser->enc_frame_len = 0;
EVP_CIPHER_CTX_free (ctx);
return ret;
}
int
handle_one_frame (struct evbuffer *buf, FrameParser *parser)
{
struct evbuffer *input = buf;
if (!parser->enc_frame_len) {
/* Read the length of the encrypted frame first. */
if (evbuffer_get_length (input) < sizeof(int))
return 0;
int frame_len;
evbuffer_remove (input, &frame_len, sizeof(int));
parser->enc_frame_len = ntohl (frame_len);
if (evbuffer_get_length (input) > 0)
return handle_frame_content (buf, parser);
return 0;
} else {
return handle_frame_content (buf, parser);
}
}
static int
handle_frame_fragment_content (struct evbuffer *buf, FrameParser *parser)
{
char *fragment = NULL, *out = NULL;
int fragment_len, outlen;
int ret = 0;
struct evbuffer *input = buf;
fragment_len = evbuffer_get_length (input);
fragment = g_malloc (fragment_len);
evbuffer_remove (input, fragment, fragment_len);
out = g_malloc (fragment_len + ENC_BLOCK_SIZE);
if (EVP_DecryptUpdate (parser->ctx,
(unsigned char *)out, &outlen,
(unsigned char *)fragment, fragment_len) == 0) {
seaf_warning ("Failed to decrypt frame fragment.\n");
ret = -1;
goto out;
}
ret = parser->fragment_cb (out, outlen, 0, parser->cbarg);
if (ret < 0)
goto out;
parser->remain -= fragment_len;
if (parser->remain <= 0) {
if (EVP_DecryptFinal_ex (parser->ctx,
(unsigned char *)out,
&outlen) == 0) {
seaf_warning ("Failed to decrypt frame fragment.\n");
ret = -1;
goto out;
}
ret = parser->fragment_cb (out, outlen, 1, parser->cbarg);
if (ret < 0)
goto out;
EVP_CIPHER_CTX_free (parser->ctx);
parser->enc_init = FALSE;
parser->enc_frame_len = 0;
}
out:
g_free (fragment);
g_free (out);
if (ret < 0) {
EVP_CIPHER_CTX_free (parser->ctx);
parser->enc_init = FALSE;
parser->enc_frame_len = 0;
}
return ret;
}
int
handle_frame_fragments (struct evbuffer *buf, FrameParser *parser)
{
struct evbuffer *input = buf;
if (!parser->enc_frame_len) {
/* Read the length of the encrypted frame first. */
if (evbuffer_get_length (input) < sizeof(int))
return 0;
int frame_len;
evbuffer_remove (input, &frame_len, sizeof(int));
parser->enc_frame_len = ntohl (frame_len);
parser->remain = parser->enc_frame_len;
if (parser->version == 1)
blocktx_decrypt_init (&parser->ctx, parser->key, parser->iv);
else if (parser->version == 2)
blocktx_decrypt_init (&parser->ctx, parser->key_v2, parser->iv_v2);
parser->enc_init = TRUE;
if (evbuffer_get_length (input) > 0)
return handle_frame_fragment_content (buf, parser);
return 0;
} else {
return handle_frame_fragment_content (buf, parser);
}
}
================================================
FILE: common/block-tx-utils.h
================================================
#ifndef BLOCK_TX_UTILS_H
#define BLOCK_TX_UTILS_H
#include <event2/buffer.h>
#include <event2/util.h>
#include <openssl/evp.h>
/* Common structures and contants shared by the client and server. */
/* We use AES 256 */
#define ENC_KEY_SIZE 32
#define ENC_BLOCK_SIZE 16
#define BLOCK_PROTOCOL_VERSION 2
enum {
STATUS_OK = 0,
STATUS_VERSION_MISMATCH,
STATUS_BAD_REQUEST,
STATUS_ACCESS_DENIED,
STATUS_INTERNAL_SERVER_ERROR,
STATUS_NOT_FOUND,
};
struct _HandshakeRequest {
gint32 version;
gint32 key_len;
char enc_session_key[0];
} __attribute__((__packed__));
typedef struct _HandshakeRequest HandshakeRequest;
struct _HandshakeResponse {
gint32 status;
gint32 version;
} __attribute__((__packed__));
typedef struct _HandshakeResponse HandshakeResponse;
struct _AuthResponse {
gint32 status;
} __attribute__((__packed__));
typedef struct _AuthResponse AuthResponse;
enum {
REQUEST_COMMAND_GET = 0,
REQUEST_COMMAND_PUT,
};
struct _RequestHeader {
gint32 command;
char block_id[40];
} __attribute__((__packed__));
typedef struct _RequestHeader RequestHeader;
struct _ResponseHeader {
gint32 status;
} __attribute__((__packed__));
typedef struct _ResponseHeader ResponseHeader;
/* Utility functions for encryption. */
void
blocktx_generate_encrypt_key (unsigned char *session_key, int sk_len,
unsigned char *key, unsigned char *iv);
int
blocktx_encrypt_init (EVP_CIPHER_CTX **ctx,
const unsigned char *key,
const unsigned char *iv);
int
blocktx_decrypt_init (EVP_CIPHER_CTX **ctx,
const unsigned char *key,
const unsigned char *iv);
/*
* Encrypted data is sent in "frames".
* Format of a frame:
*
* length of data in the frame after encryption + encrypted data.
*
* Each frame can contain three types of contents:
* 1. Auth request or response;
* 2. Block request or response header;
* 3. Block content.
*/
int
send_encrypted_data_frame_begin (evutil_socket_t data_fd,
int frame_len);
int
send_encrypted_data (EVP_CIPHER_CTX *ctx,
evutil_socket_t data_fd,
const void *buf, int len);
int
send_encrypted_data_frame_end (EVP_CIPHER_CTX *ctx,
evutil_socket_t data_fd);
typedef int (*FrameContentCB) (char *, int, void *);
typedef int (*FrameFragmentCB) (char *, int, int, void *);
typedef struct _FrameParser {
int enc_frame_len;
unsigned char key[ENC_KEY_SIZE];
unsigned char iv[ENC_BLOCK_SIZE];
gboolean enc_init;
EVP_CIPHER_CTX *ctx;
unsigned char key_v2[ENC_KEY_SIZE];
unsigned char iv_v2[ENC_BLOCK_SIZE];
int version;
/* Used when parsing fragments */
int remain;
FrameContentCB content_cb;
FrameFragmentCB fragment_cb;
void *cbarg;
} FrameParser;
/* Handle entire frame all at once.
* parser->content_cb() will be called after the entire frame is read.
*/
int
handle_one_frame (struct evbuffer *buf, FrameParser *parser);
/* Handle a frame fragment by fragment.
* parser->fragment_cb() will be called when any amount data is read.
*/
int
handle_frame_fragments (struct evbuffer *buf, FrameParser *parser);
#endif
================================================
FILE: common/block.h
================================================
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
#ifndef BLOCK_H
#define BLOCK_H
typedef struct _BMetadata BlockMetadata;
typedef struct _BMetadata BMetadata;
struct _BMetadata {
char id[41];
uint32_t size;
};
/* Opaque block handle.
*/
typedef struct _BHandle BlockHandle;
typedef struct _BHandle BHandle;
enum {
BLOCK_READ,
BLOCK_WRITE,
};
typedef gboolean (*SeafBlockFunc) (const char *store_id,
int version,
const char *block_id,
void *user_data);
#endif
================================================
FILE: common/branch-mgr.c
================================================
#include "common.h"
#include "log.h"
#ifndef SEAFILE_SERVER
#include "db.h"
#else
#include "seaf-db.h"
#endif
#include "seafile-session.h"
#ifdef FULL_FEATURE
#include "notif-mgr.h"
#endif
#include "branch-mgr.h"
#define BRANCH_DB "branch.db"
SeafBranch *
seaf_branch_new (const char *name, const char *repo_id, const char *commit_id)
{
SeafBranch *branch;
branch = g_new0 (SeafBranch, 1);
branch->name = g_strdup (name);
memcpy (branch->repo_id, repo_id, 36);
branch->repo_id[36] = '\0';
memcpy (branch->commit_id, commit_id, 40);
branch->commit_id[40] = '\0';
branch->ref = 1;
return branch;
}
void
seaf_branch_free (SeafBranch *branch)
{
if (branch == NULL) return;
g_free (branch->name);
g_free (branch);
}
void
seaf_branch_list_free (GList *blist)
{
GList *ptr;
for (ptr = blist; ptr; ptr = ptr->next) {
seaf_branch_unref (ptr->data);
}
g_list_free (blist);
}
void
seaf_branch_set_commit (SeafBranch *branch, const char *commit_id)
{
memcpy (branch->commit_id, commit_id, 40);
branch->commit_id[40] = '\0';
}
void
seaf_branch_ref (SeafBranch *branch)
{
branch->ref++;
}
void
seaf_branch_unref (SeafBranch *branch)
{
if (!branch)
return;
if (--branch->ref <= 0)
seaf_branch_free (branch);
}
struct _SeafBranchManagerPriv {
sqlite3 *db;
#ifndef SEAFILE_SERVER
pthread_mutex_t db_lock;
#endif
};
static int open_db (SeafBranchManager *mgr);
SeafBranchManager *
seaf_branch_manager_new (struct _SeafileSession *seaf)
{
SeafBranchManager *mgr;
mgr = g_new0 (SeafBranchManager, 1);
mgr->priv = g_new0 (SeafBranchManagerPriv, 1);
mgr->seaf = seaf;
#ifndef SEAFILE_SERVER
pthread_mutex_init (&mgr->priv->db_lock, NULL);
#endif
return mgr;
}
int
seaf_branch_manager_init (SeafBranchManager *mgr)
{
return open_db (mgr);
}
static int
open_db (SeafBranchManager *mgr)
{
if (!mgr->seaf->create_tables && seaf_db_type (mgr->seaf->db) != SEAF_DB_TYPE_PGSQL)
return 0;
#ifndef SEAFILE_SERVER
char *db_path;
const char *sql;
db_path = g_build_filename (mgr->seaf->seaf_dir, BRANCH_DB, NULL);
if (sqlite_open_db (db_path, &mgr->priv->db) < 0) {
g_critical ("[Branch mgr] Failed to open branch db\n");
g_free (db_path);
return -1;
}
g_free (db_path);
sql = "CREATE TABLE IF NOT EXISTS Branch ("
"name TEXT, repo_id TEXT, commit_id TEXT);";
if (sqlite_query_exec (mgr->priv->db, sql) < 0)
return -1;
sql = "CREATE INDEX IF NOT EXISTS branch_index ON Branch(repo_id, name);";
if (sqlite_query_exec (mgr->priv->db, sql) < 0)
return -1;
#elif defined FULL_FEATURE
char *sql;
switch (seaf_db_type (mgr->seaf->db)) {
case SEAF_DB_TYPE_MYSQL:
sql = "CREATE TABLE IF NOT EXISTS Branch ("
"id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, "
"name VARCHAR(10), repo_id CHAR(41), commit_id CHAR(41),"
"UNIQUE INDEX(repo_id, name)) ENGINE = INNODB";
if (seaf_db_query (mgr->seaf->db, sql) < 0)
return -1;
break;
case SEAF_DB_TYPE_PGSQL:
sql = "CREATE TABLE IF NOT EXISTS Branch ("
"name VARCHAR(10), repo_id CHAR(40), commit_id CHAR(40),"
"PRIMARY KEY (repo_id, name))";
if (seaf_db_query (mgr->seaf->db, sql) < 0)
return -1;
break;
case SEAF_DB_TYPE_SQLITE:
sql = "CREATE TABLE IF NOT EXISTS Branch ("
"name VARCHAR(10), repo_id CHAR(41), commit_id CHAR(41),"
"PRIMARY KEY (repo_id, name))";
if (seaf_db_query (mgr->seaf->db, sql) < 0)
return -1;
break;
}
#endif
return 0;
}
int
seaf_branch_manager_add_branch (SeafBranchManager *mgr, SeafBranch *branch)
{
#ifndef SEAFILE_SERVER
char sql[256];
pthread_mutex_lock (&mgr->priv->db_lock);
sqlite3_snprintf (sizeof(sql), sql,
"SELECT 1 FROM Branch WHERE name=%Q and repo_id=%Q",
branch->name, branch->repo_id);
if (sqlite_check_for_existence (mgr->priv->db, sql))
sqlite3_snprintf (sizeof(sql), sql,
"UPDATE Branch SET commit_id=%Q WHERE "
"name=%Q and repo_id=%Q",
branch->commit_id, branch->name, branch->repo_id);
else
sqlite3_snprintf (sizeof(sql), sql,
"INSERT INTO Branch (name, repo_id, commit_id) VALUES (%Q, %Q, %Q)",
branch->name, branch->repo_id, branch->commit_id);
sqlite_query_exec (mgr->priv->db, sql);
pthread_mutex_unlock (&mgr->priv->db_lock);
return 0;
#else
char *sql;
SeafDB *db = mgr->seaf->db;
if (seaf_db_type(db) == SEAF_DB_TYPE_PGSQL) {
gboolean exists, err;
int rc;
sql = "SELECT repo_id FROM Branch WHERE name=? AND repo_id=?";
exists = seaf_db_statement_exists(db, sql, &err,
2, "string", branch->name,
"string", branch->repo_id);
if (err)
return -1;
if (exists)
rc = seaf_db_statement_query (db,
"UPDATE Branch SET commit_id=? "
"WHERE name=? AND repo_id=?",
3, "string", branch->commit_id,
"string", branch->name,
"string", branch->repo_id);
else
rc = seaf_db_statement_query (db,
"INSERT INTO Branch (name, repo_id, commit_id) VALUES (?, ?, ?)",
3, "string", branch->name,
"string", branch->repo_id,
"string", branch->commit_id);
if (rc < 0)
return -1;
} else {
int rc = seaf_db_statement_query (db,
"REPLACE INTO Branch (name, repo_id, commit_id) VALUES (?, ?, ?)",
3, "string", branch->name,
"string", branch->repo_id,
"string", branch->commit_id);
if (rc < 0)
return -1;
}
return 0;
#endif
}
int
seaf_branch_manager_del_branch (SeafBranchManager *mgr,
const char *repo_id,
const char *name)
{
#ifndef SEAFILE_SERVER
char *sql;
pthread_mutex_lock (&mgr->priv->db_lock);
sql = sqlite3_mprintf ("DELETE FROM Branch WHERE name = %Q AND "
"repo_id = '%s'", name, repo_id);
if (sqlite_query_exec (mgr->priv->db, sql) < 0)
seaf_warning ("Delete branch %s failed\n", name);
sqlite3_free (sql);
pthread_mutex_unlock (&mgr->priv->db_lock);
return 0;
#else
int rc = seaf_db_statement_query (mgr->seaf->db,
"DELETE FROM Branch WHERE name=? AND repo_id=?",
2, "string", name, "string", repo_id);
if (rc < 0)
return -1;
return 0;
#endif
}
int
seaf_branch_manager_update_branch (SeafBranchManager *mgr, SeafBranch *branch)
{
#ifndef SEAFILE_SERVER
sqlite3 *db;
char *sql;
pthread_mutex_lock (&mgr->priv->db_lock);
db = mgr->priv->db;
sql = sqlite3_mprintf ("UPDATE Branch SET commit_id = %Q "
"WHERE name = %Q AND repo_id = %Q",
branch->commit_id, branch->name, branch->repo_id);
sqlite_query_exec (db, sql);
sqlite3_free (sql);
pthread_mutex_unlock (&mgr->priv->db_lock);
return 0;
#else
int rc = seaf_db_statement_query (mgr->seaf->db,
"UPDATE Branch SET commit_id = ? "
"WHERE name = ? AND repo_id = ?",
3, "string", branch->commit_id,
"string", branch->name,
"string", branch->repo_id);
if (rc < 0)
return -1;
return 0;
#endif
}
#if defined( SEAFILE_SERVER ) && defined( FULL_FEATURE )
#include "mq-mgr.h"
static gboolean
get_commit_id (SeafDBRow *row, void *data)
{
char *out_commit_id = data;
const char *commit_id;
commit_id = seaf_db_row_get_column_text (row, 0);
memcpy (out_commit_id, commit_id, 41);
out_commit_id[40] = '\0';
return FALSE;
}
static void
publish_repo_update_event (const char *repo_id, const char *commit_id)
{
json_t *msg = json_object ();
char *msg_str = NULL;
json_object_set_new (msg, "msg_type", json_string("repo-update"));
json_object_set_new (msg, "repo_id", json_string(repo_id));
json_object_set_new (msg, "commit_id", json_string(commit_id));
msg_str = json_dumps (msg, JSON_PRESERVE_ORDER);
seaf_mq_manager_publish_event (seaf->mq_mgr, SEAFILE_SERVER_CHANNEL_EVENT, msg_str);
g_free (msg_str);
json_decref (msg);
}
static void
notify_repo_update (const char *repo_id, const char *commit_id)
{
json_t *event = NULL;
json_t *content = NULL;
char *msg = NULL;
event = json_object ();
content = json_object ();
json_object_set_new (event, "type", json_string("repo-update"));
json_object_set_new (content, "repo_id", json_string(repo_id));
json_object_set_new (content, "commit_id", json_string(commit_id));
json_object_set_new (event, "content", content);
msg = json_dumps (event, JSON_COMPACT);
if (seaf->notif_mgr)
seaf_notif_manager_send_event (seaf->notif_mgr, msg);
json_decref (event);
g_free (msg);
}
static void
on_branch_updated (SeafBranchManager *mgr, SeafBranch *branch)
{
if (seaf->is_repair)
return;
seaf_repo_manager_update_repo_info (seaf->repo_mgr, branch->repo_id, branch->commit_id);
notify_repo_update(branch->repo_id, branch->commit_id);
if (seaf_repo_manager_is_virtual_repo (seaf->repo_mgr, branch->repo_id))
return;
publish_repo_update_event (branch->repo_id, branch->commit_id);
}
static gboolean
get_gc_id (SeafDBRow *row, void *data)
{
char **out_gc_id = data;
*out_gc_id = g_strdup(seaf_db_row_get_column_text (row, 0));
return FALSE;
}
int
seaf_branch_manager_test_and_update_branch (SeafBranchManager *mgr,
SeafBranch *branch,
const char *old_commit_id,
gboolean check_gc,
const char *last_gc_id,
const char *origin_repo_id,
gboolean *gc_conflict)
{
SeafDBTrans *trans;
char *sql;
char commit_id[41] = { 0 };
char *gc_id = NULL;
if (check_gc)
*gc_conflict = FALSE;
trans = seaf_db_begin_transaction (mgr->seaf->db);
if (!trans)
return -1;
if (check_gc) {
sql = "SELECT gc_id FROM GCID WHERE repo_id = ? FOR UPDATE";
if (!origin_repo_id) {
if (seaf_db_trans_foreach_selected_row (trans, sql,
get_gc_id, &gc_id,
1, "string", branch->repo_id) < 0) {
seaf_db_rollback (trans);
seaf_db_trans_close (trans);
return -1;
}
}
else {
if (seaf_db_trans_foreach_selected_row (trans, sql,
get_gc_id, &gc_id,
1, "string", origin_repo_id) < 0) {
seaf_db_rollback (trans);
seaf_db_trans_close (trans);
return -1;
}
}
if (g_strcmp0 (last_gc_id, gc_id) != 0) {
seaf_warning ("Head branch update for repo %s conflicts with GC.\n",
branch->repo_id);
seaf_db_rollback (trans);
seaf_db_trans_close (trans);
*gc_conflict = TRUE;
g_free (gc_id);
return -1;
}
g_free (gc_id);
}
switch (seaf_db_type (mgr->seaf->db)) {
case SEAF_DB_TYPE_MYSQL:
case SEAF_DB_TYPE_PGSQL:
sql = "SELECT commit_id FROM Branch WHERE name=? "
"AND repo_id=? FOR UPDATE";
break;
case SEAF_DB_TYPE_SQLITE:
sql = "SELECT commit_id FROM Branch WHERE name=? "
"AND repo_id=?";
break;
default:
g_return_val_if_reached (-1);
}
if (seaf_db_trans_foreach_selected_row (trans, sql,
get_commit_id, commit_id,
2, "string", branch->name,
"string", branch->repo_id) < 0) {
seaf_db_rollback (trans);
seaf_db_trans_close (trans);
return -1;
}
if (strcmp (old_commit_id, commit_id) != 0) {
seaf_db_rollback (trans);
seaf_db_trans_close (trans);
return -1;
}
sql = "UPDATE Branch SET commit_id = ? "
"WHERE name = ? AND repo_id = ?";
if (seaf_db_trans_query (trans, sql, 3, "string", branch->commit_id,
"string", branch->name,
"string", branch->repo_id) < 0) {
seaf_db_rollback (trans);
seaf_db_trans_close (trans);
return -1;
}
if (seaf_db_commit (trans) < 0) {
seaf_db_rollback (trans);
seaf_db_trans_close (trans);
return -1;
}
seaf_db_trans_close (trans);
on_branch_updated (mgr, branch);
return 0;
}
#endif
#ifndef SEAFILE_SERVER
static SeafBranch *
real_get_branch (SeafBranchManager *mgr,
const char *repo_id,
const char *name)
{
SeafBranch *branch = NULL;
sqlite3_stmt *stmt;
sqlite3 *db;
char *sql;
int result;
pthread_mutex_lock (&mgr->priv->db_lock);
db = mgr->priv->db;
sql = sqlite3_mprintf ("SELECT commit_id FROM Branch "
"WHERE name = %Q and repo_id='%s'",
name, repo_id);
if (!(stmt = sqlite_query_prepare (db, sql))) {
seaf_warning ("[Branch mgr] Couldn't prepare query %s\n", sql);
sqlite3_free (sql);
pthread_mutex_unlock (&mgr->priv->db_lock);
return NULL;
}
sqlite3_free (sql);
result = sqlite3_step (stmt);
if (result == SQLITE_ROW) {
char *commit_id = (char *)sqlite3_column_text (stmt, 0);
branch = seaf_branch_new (name, repo_id, commit_id);
pthread_mutex_unlock (&mgr->priv->db_lock);
sqlite3_finalize (stmt);
return branch;
} else if (result == SQLITE_ERROR) {
const char *str = sqlite3_errmsg (db);
seaf_warning ("Couldn't prepare query, error: %d->'%s'\n",
result, str ? str : "no error given");
}
sqlite3_finalize (stmt);
pthread_mutex_unlock (&mgr->priv->db_lock);
return NULL;
}
SeafBranch *
seaf_branch_manager_get_branch (SeafBranchManager *mgr,
const char *repo_id,
const char *name)
{
SeafBranch *branch;
/* "fetch_head" maps to "local" or "master" on client (LAN sync) */
if (strcmp (name, "fetch_head") == 0) {
branch = real_get_branch (mgr, repo_id, "local");
if (!branch) {
branch = real_get_branch (mgr, repo_id, "master");
}
return branch;
} else {
return real_get_branch (mgr, repo_id, name);
}
}
#else
static gboolean
get_branch (SeafDBRow *row, void *vid)
{
char *ret = vid;
const char *commit_id;
commit_id = seaf_db_row_get_column_text (row, 0);
memcpy (ret, commit_id, 41);
return FALSE;
}
static SeafBranch *
real_get_branch (SeafBranchManager *mgr,
const char *repo_id,
const char *name)
{
char commit_id[41];
char *sql;
commit_id[0] = 0;
sql = "SELECT commit_id FROM Branch WHERE name=? AND repo_id=?";
if (seaf_db_statement_foreach_row (mgr->seaf->db, sql,
get_branch, commit_id,
2, "string", name, "string", repo_id) < 0) {
seaf_warning ("[branch mgr] DB error when get branch %s.\n", name);
return NULL;
}
if (commit_id[0] == 0)
return NULL;
return seaf_branch_new (name, repo_id, commit_id);
}
SeafBranch *
seaf_branch_manager_get_branch (SeafBranchManager *mgr,
const char *repo_id,
const char *name)
{
SeafBranch *branch;
/* "fetch_head" maps to "master" on server. */
if (strcmp (name, "fetch_head") == 0) {
branch = real_get_branch (mgr, repo_id, "master");
return branch;
} else {
return real_get_branch (mgr, repo_id, name);
}
}
#endif /* not SEAFILE_SERVER */
gboolean
seaf_branch_manager_branch_exists (SeafBranchManager *mgr,
const char *repo_id,
const char *name)
{
#ifndef SEAFILE_SERVER
char *sql;
gboolean ret;
pthread_mutex_lock (&mgr->priv->db_lock);
sql = sqlite3_mprintf ("SELECT name FROM Branch WHERE name = %Q "
"AND repo_id='%s'", name, repo_id);
ret = sqlite_check_for_existence (mgr->priv->db, sql);
sqlite3_free (sql);
pthread_mutex_unlock (&mgr->priv->db_lock);
return ret;
#else
gboolean db_err = FALSE;
return seaf_db_statement_exists (mgr->seaf->db,
"SELECT name FROM Branch WHERE name=? "
"AND repo_id=?", &db_err,
2, "string", name, "string", repo_id);
#endif
}
#ifndef SEAFILE_SERVER
GList *
seaf_branch_manager_get_branch_list (SeafBranchManager *mgr,
const char *repo_id)
{
sqlite3 *db = mgr->priv->db;
int result;
sqlite3_stmt *stmt;
char sql[256];
char *name;
char *commit_id;
GList *ret = NULL;
SeafBranch *branch;
snprintf (sql, 256, "SELECT name, commit_id FROM branch WHERE repo_id ='%s'",
repo_id);
pthread_mutex_lock (&mgr->priv->db_lock);
if ( !(stmt = sqlite_query_prepare(db, sql)) ) {
pthread_mutex_unlock (&mgr->priv->db_lock);
return NULL;
}
while (1) {
result = sqlite3_step (stmt);
if (result == SQLITE_ROW) {
name = (char *)sqlite3_column_text(stmt, 0);
commit_id = (char *)sqlite3_column_text(stmt, 1);
branch = seaf_branch_new (name, repo_id, commit_id);
ret = g_list_prepend (ret, branch);
}
if (result == SQLITE_DONE)
break;
if (result == SQLITE_ERROR) {
const gchar *str = sqlite3_errmsg (db);
seaf_warning ("Couldn't prepare query, error: %d->'%s'\n",
result, str ? str : "no error given");
sqlite3_finalize (stmt);
seaf_branch_list_free (ret);
pthread_mutex_unlock (&mgr->priv->db_lock);
return NULL;
}
}
sqlite3_finalize (stmt);
pthread_mutex_unlock (&mgr->priv->db_lock);
return g_list_reverse(ret);
}
#else
static gboolean
get_branches (SeafDBRow *row, void *vplist)
{
GList **plist = vplist;
const char *commit_id;
const char *name;
const char *repo_id;
SeafBranch *branch;
name = seaf_db_row_get_column_text (row, 0);
repo_id = seaf_db_row_get_column_text (row, 1);
commit_id = seaf_db_row_get_column_text (row, 2);
branch = seaf_branch_new (name, repo_id, commit_id);
*plist = g_list_prepend (*plist, branch);
return TRUE;
}
GList *
seaf_branch_manager_get_branch_list (SeafBranchManager *mgr,
const char *repo_id)
{
GList *ret = NULL;
char *sql;
sql = "SELECT name, repo_id, commit_id FROM Branch WHERE repo_id=?";
if (seaf_db_statement_foreach_row (mgr->seaf->db, sql,
get_branches, &ret,
1, "string", repo_id) < 0) {
seaf_warning ("[branch mgr] DB error when get branch list.\n");
return NULL;
}
return ret;
}
#endif
================================================
FILE: common/branch-mgr.h
================================================
#ifndef SEAF_BRANCH_MGR_H
#define SEAF_BRANCH_MGR_H
#include "commit-mgr.h"
#define NO_BRANCH "-"
typedef struct _SeafBranch SeafBranch;
struct _SeafBranch {
int ref;
char *name;
char repo_id[37];
char commit_id[41];
};
SeafBranch *seaf_branch_new (const char *name,
const char *repo_id,
const char *commit_id);
void seaf_branch_free (SeafBranch *branch);
void seaf_branch_set_commit (SeafBranch *branch, const char *commit_id);
void seaf_branch_ref (SeafBranch *branch);
void seaf_branch_unref (SeafBranch *branch);
typedef struct _SeafBranchManager SeafBranchManager;
typedef struct _SeafBranchManagerPriv SeafBranchManagerPriv;
struct _SeafileSession;
struct _SeafBranchManager {
struct _SeafileSession *seaf;
SeafBranchManagerPriv *priv;
};
SeafBranchManager *seaf_branch_manager_new (struct _SeafileSession *seaf);
int seaf_branch_manager_init (SeafBranchManager *mgr);
int
seaf_branch_manager_add_branch (SeafBranchManager *mgr, SeafBranch *branch);
int
seaf_branch_manager_del_branch (SeafBranchManager *mgr,
const char *repo_id,
const char *name);
void
seaf_branch_list_free (GList *blist);
int
seaf_branch_manager_update_branch (SeafBranchManager *mgr,
SeafBranch *branch);
#ifdef SEAFILE_SERVER
/**
* Atomically test whether the current head commit id on @branch
* is the same as @old_commit_id and update branch in db.
*/
int
seaf_branch_manager_test_and_update_branch (SeafBranchManager *mgr,
SeafBranch *branch,
const char *old_commit_id,
gboolean check_gc,
const char *last_gc_id,
const char *origin_repo_id,
gboolean *gc_conflict);
#endif
SeafBranch *
seaf_branch_manager_get_branch (SeafBranchManager *mgr,
const char *repo_id,
const char *name);
gboolean
seaf_branch_manager_branch_exists (SeafBranchManager *mgr,
const char *repo_id,
const char *name);
GList *
seaf_branch_manager_get_branch_list (SeafBranchManager *mgr,
const char *repo_id);
gint64
seaf_branch_manager_calculate_branch_size (SeafBranchManager *mgr,
const char *repo_id,
const char *commit_id);
#endif /* SEAF_BRANCH_MGR_H */
================================================
FILE: common/cdc/Makefile.am
================================================
AM_CFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/lib \
-Wall @GLIB2_CFLAGS@ @MSVC_CFLAGS@
noinst_LTLIBRARIES = libcdc.la
noinst_HEADERS = cdc.h rabin-checksum.h
libcdc_la_SOURCES = cdc.c rabin-checksum.c
libcdc_la_LDFLAGS = -Wl,-z -Wl,defs
libcdc_la_LIBADD = @SSL_LIBS@ @GLIB2_LIBS@ \
$(top_builddir)/lib/libseafile_common.la
================================================
FILE: common/cdc/cdc.c
================================================
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
#include "common.h"
#include "log.h"
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <errno.h>
#include <glib/gstdio.h>
#include "utils.h"
#include "cdc.h"
#include "../seafile-crypt.h"
#include "rabin-checksum.h"
#define finger rabin_checksum
#define rolling_finger rabin_rolling_checksum
#define BLOCK_SZ (1024*1024*1)
#define BLOCK_MIN_SZ (1024*256)
#define BLOCK_MAX_SZ (1024*1024*4)
#define BLOCK_WIN_SZ 48
#define NAME_MAX_SZ 4096
#define BREAK_VALUE 0x0013 ///0x0513
#define READ_SIZE 1024 * 4
#define BYTE_TO_HEX(b) (((b)>=10)?('a'+b-10):('0'+b))
static int default_write_chunk (CDCDescriptor *chunk_descr)
{
char filename[NAME_MAX_SZ];
char chksum_str[CHECKSUM_LENGTH *2 + 1];
int fd_chunk, ret;
memset(chksum_str, 0, sizeof(chksum_str));
rawdata_to_hex (chunk_descr->checksum, chksum_str, CHECKSUM_LENGTH);
snprintf (filename, NAME_MAX_SZ, "./%s", chksum_str);
fd_chunk = g_open (filename, O_RDWR | O_CREAT | O_BINARY, 0644);
if (fd_chunk < 0)
return -1;
ret = writen (fd_chunk, chunk_descr->block_buf, chunk_descr->len);
close (fd_chunk);
return ret;
}
static int init_cdc_file_descriptor (int fd,
uint64_t file_size,
CDCFileDescriptor *file_descr)
{
int max_block_nr = 0;
int block_min_sz = 0;
file_descr->block_nr = 0;
if (file_descr->block_min_sz <= 0)
file_descr->block_min_sz = BLOCK_MIN_SZ;
if (file_descr->block_max_sz <= 0)
file_descr->block_max_sz = BLOCK_MAX_SZ;
if (file_descr->block_sz <= 0)
file_descr->block_sz = BLOCK_SZ;
if (file_descr->write_block == NULL)
file_descr->write_block = (WriteblockFunc)default_write_chunk;
block_min_sz = file_descr->block_min_sz;
max_block_nr = ((file_size + block_min_sz - 1) / block_min_sz);
file_descr->blk_sha1s = (uint8_t *)calloc (sizeof(uint8_t),
max_block_nr * CHECKSUM_LENGTH);
file_descr->max_block_nr = max_block_nr;
return 0;
}
#define WRITE_CDC_BLOCK(block_sz, write_data) \
do { \
int _block_sz = (block_sz); \
chunk_descr.len = _block_sz; \
chunk_descr.offset = offset; \
ret = file_descr->write_block (file_descr->repo_id, \
file_descr->version, \
&chunk_descr, \
crypt, chunk_descr.checksum, \
(write_data)); \
if (ret < 0) { \
free (buf); \
g_warning ("CDC: failed to write chunk.\n"); \
return -1; \
} \
memcpy (file_descr->blk_sha1s + \
file_descr->block_nr * CHECKSUM_LENGTH, \
chunk_descr.checksum, CHECKSUM_LENGTH); \
SHA1_Update (&file_ctx, chunk_descr.checksum, 20); \
file_descr->block_nr++; \
offset += _block_sz; \
\
memmove (buf, buf + _block_sz, tail - _block_sz); \
tail = tail - _block_sz; \
cur = 0; \
}while(0);
/* content-defined chunking */
int file_chunk_cdc(int fd_src,
CDCFileDescriptor *file_descr,
SeafileCrypt *crypt,
gboolean write_data,
gint64 *indexed)
{
char *buf;
uint32_t buf_sz;
SHA_CTX file_ctx;
CDCDescriptor chunk_descr;
SHA1_Init (&file_ctx);
SeafStat sb;
if (seaf_fstat (fd_src, &sb) < 0) {
seaf_warning ("CDC: failed to stat: %s.\n", strerror(errno));
return -1;
}
uint64_t expected_size = sb.st_size;
init_cdc_file_descriptor (fd_src, expected_size, file_descr);
uint32_t block_min_sz = file_descr->block_min_sz;
uint32_t block_mask = file_descr->block_sz - 1;
int fingerprint = 0;
int offset = 0;
int ret = 0;
int tail, cur, rsize;
buf_sz = file_descr->block_max_sz;
buf = chunk_descr.block_buf = malloc (buf_sz);
if (!buf)
return -1;
/* buf: a fix-sized buffer.
* cur: data behind (inclusive) this offset has been scanned.
* cur + 1 is the bytes that has been scanned.
* tail: length of data loaded into memory. buf[tail] is invalid.
*/
tail = cur = 0;
while (1) {
if (tail < block_min_sz) {
rsize = block_min_sz - tail + READ_SIZE;
} else {
rsize = (buf_sz - tail < READ_SIZE) ? (buf_sz - tail) : READ_SIZE;
}
ret = readn (fd_src, buf + tail, rsize);
if (ret < 0) {
seaf_warning ("CDC: failed to read: %s.\n", strerror(errno));
free (buf);
return -1;
}
tail += ret;
file_descr->file_size += ret;
if (file_descr->file_size > expected_size) {
seaf_warning ("File size changed while chunking.\n");
free (buf);
return -1;
}
/* We've read all the data in this file. Output the block immediately
* in two cases:
* 1. The data left in the file is less than block_min_sz;
* 2. We cannot find the break value until the end of this file.
*/
if (tail < block_min_sz || cur >= tail) {
if (tail > 0) {
if (file_descr->block_nr == file_descr->max_block_nr) {
seaf_warning ("Block id array is not large enough, bail out.\n");
free (buf);
return -1;
}
gint64 idx_size = tail;
WRITE_CDC_BLOCK (tail, write_data);
if (indexed)
*indexed += idx_size;
}
break;
}
/*
* A block is at least of size block_min_sz.
*/
if (cur < block_min_sz - 1)
cur = block_min_sz - 1;
while (cur < tail) {
fingerprint = (cur == block_min_sz - 1) ?
finger(buf + cur - BLOCK_WIN_SZ + 1, BLOCK_WIN_SZ) :
rolling_finger (fingerprint, BLOCK_WIN_SZ,
*(buf+cur-BLOCK_WIN_SZ), *(buf + cur));
/* get a chunk, write block info to chunk file */
if (((fingerprint & block_mask) == ((BREAK_VALUE & block_mask)))
|| cur + 1 >= file_descr->block_max_sz)
{
if (file_descr->block_nr == file_descr->max_block_nr) {
seaf_warning ("Block id array is not large enough, bail out.\n");
free (buf);
return -1;
}
gint64 idx_size = cur + 1;
WRITE_CDC_BLOCK (cur + 1, write_data);
if (indexed)
*indexed += idx_size;
break;
} else {
cur ++;
}
}
}
SHA1_Final (file_descr->file_sum, &file_ctx);
free (buf);
return 0;
}
int filename_chunk_cdc(const char *filename,
CDCFileDescriptor *file_descr,
SeafileCrypt *crypt,
gboolean write_data,
gint64 *indexed)
{
int fd_src = seaf_util_open (filename, O_RDONLY | O_BINARY);
if (fd_src < 0) {
seaf_warning ("CDC: failed to open %s.\n", filename);
return -1;
}
int ret = file_chunk_cdc (fd_src, file_descr, crypt, write_data, indexed);
close (fd_src);
return ret;
}
void cdc_init ()
{
rabin_init (BLOCK_WIN_SZ);
}
================================================
FILE: common/cdc/cdc.h
================================================
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
#ifndef _CDC_H
#define _CDC_H
#include <glib.h>
#include <stdint.h>
#ifdef HAVE_MD5
#include "md5.h"
#define get_checksum md5
#define CHECKSUM_LENGTH 16
#else
#include <openssl/sha.h>
#define get_checksum sha1
#define CHECKSUM_LENGTH 20
#endif
#ifndef O_BINARY
#define O_BINARY 0
#endif
struct _CDCFileDescriptor;
struct _CDCDescriptor;
struct SeafileCrypt;
typedef int (*WriteblockFunc)(const char *repo_id,
int version,
struct _CDCDescriptor *chunk_descr,
struct SeafileCrypt *crypt,
uint8_t *checksum,
gboolean write_data);
/* define chunk file header and block entry */
typedef struct _CDCFileDescriptor {
uint32_t block_min_sz;
uint32_t block_max_sz;
uint32_t block_sz;
uint64_t file_size;
uint32_t block_nr;
uint8_t *blk_sha1s;
int max_block_nr;
uint8_t file_sum[CHECKSUM_LENGTH];
WriteblockFunc write_block;
char repo_id[37];
int version;
} CDCFileDescriptor;
typedef struct _CDCDescriptor {
uint64_t offset;
uint32_t len;
uint8_t checksum[CHECKSUM_LENGTH];
char *block_buf;
int result;
} CDCDescriptor;
int file_chunk_cdc(int fd_src,
CDCFileDescriptor *file_descr,
struct SeafileCrypt *crypt,
gboolean write_data,
gint64 *indexed);
int filename_chunk_cdc(const char *filename,
CDCFileDescriptor *file_descr,
struct SeafileCrypt *crypt,
gboolean write_data,
gint64 *indexed);
void cdc_init ();
#endif
================================================
FILE: common/cdc/rabin-checksum.c
================================================
#include <sys/types.h>
#include "rabin-checksum.h"
#ifdef WIN32
#include <stdint.h>
#ifndef u_int
typedef unsigned int u_int;
#endif
#ifndef u_char
typedef unsigned char u_char;
#endif
#ifndef u_short
typedef unsigned short u_short;
#endif
#ifndef u_long
typedef unsigned long u_long;
#endif
#ifndef u_int16_t
typedef uint16_t u_int16_t;
#endif
#ifndef u_int32_t
typedef uint32_t u_int32_t;
#endif
#ifndef u_int64_t
typedef uint64_t u_int64_t;
#endif
#endif
#define INT64(n) n##LL
#define MSB64 INT64(0x8000000000000000)
static u_int64_t poly = 0xbfe6b8a5bf378d83LL;
static u_int64_t T[256];
static u_int64_t U[256];
static int shift;
/* Highest bit set in a byte */
static const char bytemsb[0x100] = {
0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
};
/* Find last set (most significant bit) */
static inline u_int fls32 (u_int32_t v)
{
if (v & 0xffff0000) {
if (v & 0xff000000)
return 24 + bytemsb[v>>24];
else
return 16 + bytemsb[v>>16];
}
if (v & 0x0000ff00)
return 8 + bytemsb[v>>8];
else
return bytemsb[v];
}
static inline char fls64 (u_int64_t v)
{
u_int32_t h;
if ((h = v >> 32))
return 32 + fls32 (h);
else
return fls32 ((u_int32_t) v);
}
u_int64_t polymod (u_int64_t nh, u_int64_t nl, u_int64_t d)
{
int i = 0;
int k = fls64 (d) - 1;
d <<= 63 - k;
if (nh) {
if (nh & MSB64)
nh ^= d;
for (i = 62; i >= 0; i--)
if (nh & ((u_int64_t) 1) << i) {
nh ^= d >> (63 - i);
nl ^= d << (i + 1);
}
}
for (i = 63; i >= k; i--)
{
if (nl & INT64 (1) << i)
nl ^= d >> (63 - i);
}
return nl;
}
void polymult (u_int64_t *php, u_int64_t *plp, u_int64_t x, u_int64_t y)
{
int i;
u_int64_t ph = 0, pl = 0;
if (x & 1)
pl = y;
for (i = 1; i < 64; i++)
if (x & (INT64 (1) << i)) {
ph ^= y >> (64 - i);
pl ^= y << i;
}
if (php)
*php = ph;
if (plp)
*plp = pl;
}
u_int64_t polymmult (u_int64_t x, u_int64_t y, u_int64_t d)
{
u_int64_t h, l;
polymult (&h, &l, x, y);
return polymod (h, l, d);
}
static u_int64_t append8 (u_int64_t p, u_char m)
{
return ((p << 8) | m) ^ T[p >> shift];
}
static void calcT (u_int64_t poly)
{
int j = 0;
int xshift = fls64 (poly) - 1;
shift = xshift - 8;
u_int64_t T1 = polymod (0, INT64 (1) << xshift, poly);
for (j = 0; j < 256; j++) {
T[j] = polymmult (j, T1, poly) | ((u_int64_t) j << xshift);
}
}
static void calcU(int size)
{
int i;
u_int64_t sizeshift = 1;
for (i = 1; i < size; i++)
sizeshift = append8 (sizeshift, 0);
for (i = 0; i < 256; i++)
U[i] = polymmult (i, sizeshift, poly);
}
void rabin_init(int len)
{
calcT(poly);
calcU(len);
}
/*
* a simple 32 bit checksum that can be upadted from end
*/
unsigned int rabin_checksum(char *buf, int len)
{
int i;
unsigned int sum = 0;
for (i = 0; i < len; ++i) {
sum = rabin_rolling_checksum (sum, len, 0, buf[i]);
}
return sum;
}
unsigned int rabin_rolling_checksum(unsigned int csum, int len,
char c1, char c2)
{
return append8(csum ^ U[(unsigned char)c1], c2);
}
================================================
FILE: common/cdc/rabin-checksum.h
================================================
#ifndef _RABIN_CHECKSUM_H
#define _RABIN_CHECKSUM_H
unsigned int rabin_checksum(char *buf, int len);
unsigned int rabin_rolling_checksum(unsigned int csum, int len, char c1, char c2);
void rabin_init (int len);
#endif
================================================
FILE: common/commit-mgr.c
================================================
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
#include "common.h"
#include "log.h"
#include <jansson.h>
#include <openssl/sha.h>
#include "utils.h"
#include "db.h"
#include "searpc-utils.h"
#include "seafile-session.h"
#include "commit-mgr.h"
#include "seaf-utils.h"
#define MAX_TIME_SKEW 259200 /* 3 days */
struct _SeafCommitManagerPriv {
int dummy;
};
static SeafCommit *
load_commit (SeafCommitManager *mgr,
const char *repo_id, int version,
const char *commit_id);
static int
save_commit (SeafCommitManager *manager,
const char *repo_id, int version,
SeafCommit *commit);
static void
delete_commit (SeafCommitManager *mgr,
const char *repo_id, int version,
const char *id);
static json_t *
commit_to_json_object (SeafCommit *commit);
static SeafCommit *
commit_from_json_object (const char *id, json_t *object);
static void compute_commit_id (SeafCommit* commit)
{
SHA_CTX ctx;
uint8_t sha1[20];
gint64 ctime_n;
SHA1_Init (&ctx);
SHA1_Update (&ctx, commit->root_id, 41);
SHA1_Update (&ctx, commit->creator_id, 41);
if (commit->creator_name)
SHA1_Update (&ctx, commit->creator_name, strlen(commit->creator_name)+1);
SHA1_Update (&ctx, commit->desc, strlen(commit->desc)+1);
/* convert to network byte order */
ctime_n = hton64 (commit->ctime);
SHA1_Update (&ctx, &ctime_n, sizeof(ctime_n));
SHA1_Final (sha1, &ctx);
rawdata_to_hex (sha1, commit->commit_id, 20);
}
SeafCommit*
seaf_commit_new (const char *commit_id,
const char *repo_id,
const char *root_id,
const char *creator_name,
const char *creator_id,
const char *desc,
guint64 ctime)
{
SeafCommit *commit;
g_return_val_if_fail (repo_id != NULL, NULL);
g_return_val_if_fail (root_id != NULL && creator_id != NULL, NULL);
commit = g_new0 (SeafCommit, 1);
memcpy (commit->repo_id, repo_id, 36);
commit->repo_id[36] = '\0';
memcpy (commit->root_id, root_id, 40);
commit->root_id[40] = '\0';
commit->creator_name = g_strdup (creator_name);
memcpy (commit->creator_id, creator_id, 40);
commit->creator_id[40] = '\0';
commit->desc = g_strdup (desc);
if (ctime == 0) {
/* TODO: use more precise timer */
commit->ctime = (gint64)time(NULL);
} else
commit->ctime = ctime;
if (commit_id == NULL)
compute_commit_id (commit);
else {
memcpy (commit->commit_id, commit_id, 40);
commit->commit_id[40] = '\0';
}
commit->ref = 1;
return commit;
}
char *
seaf_commit_to_data (SeafCommit *commit, gsize *len)
{
json_t *object;
char *json_data;
char *ret;
object = commit_to_json_object (commit);
json_data = json_dumps (object, 0);
*len = strlen (json_data);
json_decref (object);
ret = g_strdup (json_data);
free (json_data);
return ret;
}
SeafCommit *
seaf_commit_from_data (const char *id, char *data, gsize len)
{
json_t *object;
SeafCommit *commit;
json_error_t jerror;
object = json_loadb (data, len, 0, &jerror);
if (!object) {
/* Perhaps the commit object contains invalid UTF-8 character. */
if (data[len-1] == 0)
clean_utf8_data (data, len - 1);
else
clean_utf8_data (data, len);
object = json_loadb (data, len, 0, &jerror);
if (!object) {
if (jerror.text)
seaf_warning ("Failed to load commit json: %s.\n", jerror.text);
else
seaf_warning ("Failed to load commit json.\n");
return NULL;
}
}
commit = commit_from_json_object (id, object);
json_decref (object);
return commit;
}
static void
seaf_commit_free (SeafCommit *commit)
{
g_free (commit->desc);
g_free (commit->creator_name);
if (commit->parent_id) g_free (commit->parent_id);
if (commit->second_parent_id) g_free (commit->second_parent_id);
if (commit->repo_name) g_free (commit->repo_name);
if (commit->repo_desc) g_free (commit->repo_desc);
if (commit->device_name) g_free (commit->device_name);
if (commit->repo_category) g_free (commit->repo_category);
if (commit->salt) g_free (commit->salt);
g_free (commit->client_version);
g_free (commit->magic);
g_free (commit->random_key);
g_free (commit->pwd_hash);
g_free (commit->pwd_hash_algo);
g_free (commit->pwd_hash_params);
g_free (commit);
}
void
seaf_commit_ref (SeafCommit *commit)
{
commit->ref++;
}
void
seaf_commit_unref (SeafCommit *commit)
{
if (!commit)
return;
if (--commit->ref <= 0)
seaf_commit_free (commit);
}
SeafCommitManager*
seaf_commit_manager_new (SeafileSession *seaf)
{
SeafCommitManager *mgr = g_new0 (SeafCommitManager, 1);
mgr->priv = g_new0 (SeafCommitManagerPriv, 1);
mgr->seaf = seaf;
mgr->obj_store = seaf_obj_store_new (mgr->seaf, "commits");
return mgr;
}
int
seaf_commit_manager_init (SeafCommitManager *mgr)
{
if (seaf_obj_store_init (mgr->obj_store) < 0) {
seaf_warning ("[commit mgr] Failed to init commit object store.\n");
return -1;
}
return 0;
}
#if 0
inline static void
add_commit_to_cache (SeafCommitManager *mgr, SeafCommit *commit)
{
g_hash_table_insert (mgr->priv->commit_cache,
g_strdup(commit->commit_id),
commit);
seaf_commit_ref (commit);
}
inline static void
remove_commit_from_cache (SeafCommitManager *mgr, SeafCommit *commit)
{
g_hash_table_remove (mgr->priv->commit_cache, commit->commit_id);
seaf_commit_unref (commit);
}
#endif
int
seaf_commit_manager_add_commit (SeafCommitManager *mgr,
SeafCommit *commit)
{
int ret;
/* add_commit_to_cache (mgr, commit); */
if ((ret = save_commit (mgr, commit->repo_id, commit->version, commit)) < 0)
return -1;
return 0;
}
void
seaf_commit_manager_del_commit (SeafCommitManager *mgr,
const char *repo_id,
int version,
const char *id)
{
g_return_if_fail (id != NULL);
#if 0
commit = g_hash_table_lookup(mgr->priv->commit_cache, id);
if (!commit)
goto delete;
/*
* Catch ref count bug here. We have bug in commit ref, the
* following assert can't pass. TODO: fix the commit ref bug
*/
/* g_assert (commit->ref <= 1); */
remove_commit_from_cache (mgr, commit);
delete:
#endif
delete_commit (mgr, repo_id, version, id);
}
SeafCommit*
seaf_commit_manager_get_commit (SeafCommitManager *mgr,
const char *repo_id,
int version,
const char *id)
{
SeafCommit *commit;
#if 0
commit = g_hash_table_lookup (mgr->priv->commit_cache, id);
if (commit != NULL) {
seaf_commit_ref (commit);
return commit;
}
#endif
commit = load_commit (mgr, repo_id, version, id);
if (!commit)
return NULL;
/* add_commit_to_cache (mgr, commit); */
return commit;
}
SeafCommit *
seaf_commit_manager_get_commit_compatible (SeafCommitManager *mgr,
const char *repo_id,
const char *id)
{
SeafCommit *commit = NULL;
/* First try version 1 layout. */
commit = seaf_commit_manager_get_commit (mgr, repo_id, 1, id);
if (commit)
return commit;
#if defined MIGRATION || defined SEAFILE_CLIENT
/* For compatibility with version 0. */
commit = seaf_commit_manager_get_commit (mgr, repo_id, 0, id);
#endif
return commit;
}
static gint
compare_commit_by_time (gconstpointer a, gconstpointer b, gpointer unused)
{
const SeafCommit *commit_a = a;
const SeafCommit *commit_b = b;
/* Latest commit comes first in the list. */
return (commit_b->ctime - commit_a->ctime);
}
inline static int
insert_parent_commit (GList **list, GHashTable *hash,
const char *repo_id, int version,
const char *parent_id, gboolean allow_truncate)
{
SeafCommit *p;
char *key;
if (g_hash_table_lookup (hash, parent_id) != NULL)
return 0;
p = seaf_commit_manager_get_commit (seaf->commit_mgr,
repo_id, version,
parent_id);
if (!p) {
if (allow_truncate)
return 0;
seaf_warning ("Failed to find commit %s\n", parent_id);
return -1;
}
*list = g_list_insert_sorted_with_data (*list, p,
compare_commit_by_time,
NULL);
key = g_strdup (parent_id);
g_hash_table_replace (hash, key, key);
return 0;
}
gboolean
seaf_commit_manager_traverse_commit_tree_with_limit (SeafCommitManager *mgr,
const char *repo_id,
int version,
const char *head,
CommitTraverseFunc func,
int limit,
void *data,
char **next_start_commit,
gboolean skip_errors)
{
SeafCommit *commit;
GList *list = NULL;
GHashTable *commit_hash;
gboolean ret = TRUE;
/* A hash table for recording id of traversed commits. */
commit_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
commit = seaf_commit_manager_get_commit (mgr, repo_id, version, head);
if (!commit) {
seaf_warning ("Failed to find commit %s.\n", head);
g_hash_table_destroy (commit_hash);
return FALSE;
}
list = g_list_insert_sorted_with_data (list, commit,
compare_commit_by_time,
NULL);
char *key = g_strdup (commit->commit_id);
g_hash_table_replace (commit_hash, key, key);
int count = 0;
while (list) {
gboolean stop = FALSE;
commit = list->data;
list = g_list_delete_link (list, list);
if (!func (commit, data, &stop)) {
if (!skip_errors) {
seaf_commit_unref (commit);
ret = FALSE;
goto out;
}
}
if (stop) {
seaf_commit_unref (commit);
/* stop traverse down from this commit,
* but not stop traversing the tree
*/
continue;
}
if (commit->parent_id) {
if (insert_parent_commit (&list, commit_hash, repo_id, version,
commit->parent_id, FALSE) < 0) {
if (!skip_errors) {
seaf_commit_unref (commit);
ret = FALSE;
goto out;
}
}
}
if (commit->second_parent_id) {
if (insert_parent_commit (&list, commit_hash, repo_id, version,
commit->second_parent_id, FALSE) < 0) {
if (!skip_errors) {
seaf_commit_unref (commit);
ret = FALSE;
goto out;
}
}
}
seaf_commit_unref (commit);
/* Stop when limit is reached and don't stop at unmerged branch.
* If limit < 0, there is no limit;
*/
if (limit > 0 && ++count >= limit && (!list || !list->next)) {
break;
}
}
/*
* two scenarios:
* 1. list is empty, indicate scan end
* 2. list only have one commit, as start for next scan
*/
if (list) {
commit = list->data;
if (next_start_commit) {
*next_start_commit= g_strdup (commit->commit_id);
}
seaf_commit_unref (commit);
list = g_list_delete_link (list, list);
}
out:
g_hash_table_destroy (commit_hash);
while (list) {
commit = list->data;
seaf_commit_unref (commit);
list = g_list_delete_link (list, list);
}
return ret;
}
static gboolean
traverse_commit_tree_common (SeafCommitManager *mgr,
const char *repo_id,
int version,
const char *head,
CommitTraverseFunc func,
void *data,
gboolean skip_errors,
gboolean allow_truncate)
{
SeafCommit *commit;
GList *list = NULL;
GHashTable *commit_hash;
gboolean ret = TRUE;
commit = seaf_commit_manager_get_commit (mgr, repo_id, version, head);
if (!commit) {
seaf_warning ("Failed to find commit %s.\n", head);
// For head commit damaged, directly return FALSE
// user can repair head by fsck then retraverse the tree
return FALSE;
}
/* A hash table for recording id of traversed commits. */
commit_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
list = g_list_insert_sorted_with_data (list, commit,
compare_commit_by_time,
NULL);
char *key = g_strdup (commit->commit_id);
g_hash_table_replace (commit_hash, key, key);
while (list) {
gboolean stop = FALSE;
commit = list->data;
list = g_list_delete_link (list, list);
if (!func (commit, data, &stop)) {
seaf_warning("[comit-mgr] CommitTraverseFunc failed\n");
/* If skip errors, continue to traverse parents. */
if (!skip_errors) {
seaf_commit_unref (commit);
ret = FALSE;
goto out;
}
}
if (stop) {
seaf_commit_unref (commit);
/* stop traverse down from this commit,
* but not stop traversing the tree
*/
continue;
}
if (commit->parent_id) {
if (insert_parent_commit (&list, commit_hash, repo_id, version,
commit->parent_id, allow_truncate) < 0) {
seaf_warning("[comit-mgr] insert parent commit failed\n");
/* If skip errors, try insert second parent. */
if (!skip_errors) {
seaf_commit_unref (commit);
ret = FALSE;
goto out;
}
}
}
if (commit->second_parent_id) {
if (insert_parent_commit (&list, commit_hash, repo_id, version,
commit->second_parent_id, allow_truncate) < 0) {
seaf_warning("[comit-mgr]insert second parent commit failed\n");
if (!skip_errors) {
seaf_commit_unref (commit);
ret = FALSE;
goto out;
}
}
}
seaf_commit_unref (commit);
}
out:
g_hash_table_destroy (commit_hash);
while (list) {
commit = list->data;
seaf_commit_unref (commit);
list = g_list_delete_link (list, list);
}
return ret;
}
gboolean
seaf_commit_manager_traverse_commit_tree (SeafCommitManager *mgr,
const char *repo_id,
int version,
const char *head,
CommitTraverseFunc func,
void *data,
gboolean skip_errors)
{
return traverse_commit_tree_common (mgr, repo_id, version, head,
func, data, skip_errors, FALSE);
}
gboolean
seaf_commit_manager_traverse_commit_tree_truncated (SeafCommitManager *mgr,
const char *repo_id,
int version,
const char *head,
CommitTraverseFunc func,
void *data,
gboolean skip_errors)
{
return traverse_commit_tree_common (mgr, repo_id, version, head,
func, data, skip_errors, TRUE);
}
gboolean
seaf_commit_manager_commit_exists (SeafCommitManager *mgr,
const char *repo_id,
int version,
const char *id)
{
#if 0
commit = g_hash_table_lookup (mgr->priv->commit_cache, id);
if (commit != NULL)
return TRUE;
#endif
return seaf_obj_store_obj_exists (mgr->obj_store, repo_id, version, id);
}
static json_t *
commit_to_json_object (SeafCommit *commit)
{
json_t *object;
object = json_object ();
json_object_set_string_member (object, "commit_id", commit->commit_id);
json_object_set_string_member (object, "root_id", commit->root_id);
json_object_set_string_member (object, "repo_id", commit->repo_id);
if (commit->creator_name)
json_object_set_string_member (object, "creator_name", commit->creator_name);
json_object_set_string_member (object, "creator", commit->creator_id);
json_object_set_string_member (object, "description", commit->desc);
json_object_set_int_member (object, "ctime", (gint64)commit->ctime);
json_object_set_string_or_null_member (object, "parent_id", commit->parent_id);
json_object_set_string_or_null_member (object, "second_parent_id",
commit->second_parent_id);
/*
* also save repo's properties to commit file, for easy sharing of
* repo info
*/
json_object_set_string_member (object, "repo_name", commit->repo_name);
json_object_set_string_member (object, "repo_desc",
commit->repo_desc);
json_object_set_string_or_null_member (object, "repo_category",
commit->repo_category);
if (commit->device_name)
json_object_set_string_member (object, "device_name", commit->device_name);
if (commit->client_version)
json_object_set_string_member (object, "client_version", commit->client_version);
if (commit->encrypted)
json_object_set_string_member (object, "encrypted", "true");
if (commit->encrypted) {
json_object_set_int_member (object, "enc_version", commit->enc_version);
// If pwd_hash is set, the magic field is no longer included in the commit of the newly created repo.
if (commit->enc_version >= 1 && !commit->pwd_hash)
json_object_set_string_member (object, "magic", commit->magic);
if (commit->enc_version >= 2)
json_object_set_string_member (object, "key", commit->random_key);
if (commit->enc_version >= 3)
json_object_set_string_member (object, "salt", commit->salt);
if (commit->pwd_hash) {
json_object_set_string_member (object, "pwd_hash", commit->pwd_hash);
json_object_set_string_member (object, "pwd_hash_algo", commit->pwd_hash_algo);
json_object_set_string_member (object, "pwd_hash_params", commit->pwd_hash_params);
}
}
if (commit->no_local_history)
json_object_set_int_member (object, "no_local_history", 1);
if (commit->version != 0)
json_object_set_int_member (object, "version", commit->version);
if (commit->conflict)
json_object_set_int_member (object, "conflict", 1);
if (commit->new_merge)
json_object_set_int_member (object, "new_merge", 1);
if (commit->repaired)
json_object_set_int_member (object, "repaired", 1);
return object;
}
static SeafCommit *
commit_from_json_object (const char *commit_id, json_t *object)
{
SeafCommit *commit = NULL;
const char *root_id;
const char *repo_id;
const char *creator_name = NULL;
const char *creator;
const char *desc;
gint64 ctime;
const char *parent_id, *second_parent_id;
const char *repo_name;
const char *repo_desc;
const char *repo_category;
const char *device_name;
const char *client_version;
const char *encrypted = NULL;
int enc_version = 0;
const char *magic = NULL;
const char *random_key = NULL;
const char *salt = NULL;
const char *pwd_hash = NULL;
const char *pwd_hash_algo = NULL;
const char *pwd_hash_params = NULL;
int no_local_history = 0;
int version = 0;
int conflict = 0, new_merge = 0;
int repaired = 0;
root_id = json_object_get_string_member (object, "root_id");
repo_id = json_object_get_string_member (object, "repo_id");
if (json_object_has_member (object, "creator_name"))
creator_name = json_object_get_string_or_null_member (object, "creator_name");
creator = json_object_get_string_member (object, "creator");
desc = json_object_get_string_member (object, "description");
if (!desc)
desc = "";
ctime = (guint64) json_object_get_int_member (object, "ctime");
parent_id = json_object_get_string_or_null_member (object, "parent_id");
second_parent_id = json_object_get_string_or_null_member (object, "second_parent_id");
repo_name = json_object_get_string_member (object, "repo_name");
if (!repo_name)
repo_name = "";
repo_desc = json_object_get_string_member (object, "repo_desc");
if (!repo_desc)
repo_desc = "";
repo_category = json_object_get_string_or_null_member (object, "repo_category");
device_name = json_object_get_string_or_null_member (object, "device_name");
client_version = json_object_get_string_or_null_member (object, "client_version");
if (json_object_has_member (object, "encrypted"))
encrypted = json_object_get_string_or_null_member (object, "encrypted");
if (encrypted && strcmp(encrypted, "true") == 0
&& json_object_has_member (object, "enc_version")) {
enc_version = json_object_get_int_member (object, "enc_version");
magic = json_object_get_string_member (object, "magic");
pwd_hash = json_object_get_string_member (object, "pwd_hash");
pwd_hash_algo = json_object_get_string_member (object, "pwd_hash_algo");
pwd_hash_params = json_object_get_string_member (object, "pwd_hash_params");
}
if (enc_version >= 2)
random_key = json_object_get_string_member (object, "key");
if (enc_version >= 3)
salt = json_object_get_string_member (object, "salt");
if (json_object_has_member (object, "no_local_history"))
no_local_history = json_object_get_int_member (object, "no_local_history");
if (json_object_has_member (object, "version"))
version = json_object_get_int_member (object, "version");
if (json_object_has_member (object, "new_merge"))
new_merge = json_object_get_int_member (object, "new_merge");
if (json_object_has_member (object, "conflict"))
conflict = json_object_get_int_member (object, "conflict");
if (json_object_has_member (object, "repaired"))
repaired = json_object_get_int_member (object, "repaired");
/* sanity check for incoming values. */
if (!repo_id || !is_uuid_valid(repo_id) ||
!root_id || !is_object_id_valid(root_id) ||
!creator || strlen(creator) != 40 ||
(parent_id && !is_object_id_valid(parent_id)) ||
(second_parent_id && !is_object_id_valid(second_parent_id)))
return commit;
// If pwd_hash is set, the magic field is no longer included in the commit of the newly created repo.
if (!magic)
magic = pwd_hash;
switch (enc_version) {
case 0:
break;
case 1:
if (!magic || strlen(magic) != 32)
return NULL;
break;
case 2:
if (!magic || strlen(magic) != 64)
return NULL;
if (!random_key || strlen(random_key) != 96)
return NULL;
break;
case 3:
if (!magic || strlen(magic) != 64)
return NULL;
if (!random_key || strlen(random_key) != 96)
return NULL;
if (!salt || strlen(salt) != 64)
return NULL;
break;
case 4:
if (!magic || strlen(magic) != 64)
return NULL;
if (!random_key || strlen(random_key) != 96)
return NULL;
if (!salt || strlen(salt) != 64)
return NULL;
break;
default:
seaf_warning ("Unknown encryption version %d.\n", enc_version);
return NULL;
}
char *creator_name_l = creator_name ? g_ascii_strdown (creator_name, -1) : NULL;
commit = seaf_commit_new (commit_id, repo_id, root_id,
creator_name_l, creator, desc, ctime);
g_free (creator_name_l);
commit->parent_id = parent_id ? g_strdup(parent_id) : NULL;
commit->second_parent_id = second_parent_id ? g_strdup(second_parent_id) : NULL;
commit->repo_name = g_strdup(repo_name);
commit->repo_desc = g_strdup(repo_desc);
if (encrypted && strcmp(encrypted, "true") == 0)
commit->encrypted = TRUE;
else
commit->encrypted = FALSE;
if (repo_category)
commit->repo_category = g_strdup(repo_category);
commit->device_name = g_strdup(device_name);
commit->client_version = g_strdup(client_version);
if (commit->encrypted) {
commit->enc_version = enc_version;
if (enc_version >= 1 && !pwd_hash)
commit->magic = g_strdup(magic);
if (enc_version >= 2)
commit->random_key = g_strdup (random_key);
if (enc_version >= 3)
commit->salt = g_strdup(salt);
if (pwd_hash) {
commit->pwd_hash = g_strdup (pwd_hash);
commit->pwd_hash_algo = g_strdup (pwd_hash_algo);
commit->pwd_hash_params = g_strdup (pwd_hash_params);
}
}
if (no_local_history)
commit->no_local_history = TRUE;
commit->version = version;
if (new_merge)
commit->new_merge = TRUE;
if (conflict)
commit->conflict = TRUE;
if (repaired)
commit->repaired = TRUE;
return commit;
}
static SeafCommit *
load_commit (SeafCommitManager *mgr,
const char *repo_id,
int version,
const char *commit_id)
{
char *data = NULL;
int len;
SeafCommit *commit = NULL;
json_t *object = NULL;
json_error_t jerror;
if (!commit_id || strlen(commit_id) != 40)
return NULL;
if (seaf_obj_store_read_obj (mgr->obj_store, repo_id, version,
commit_id, (void **)&data, &len) < 0)
return NULL;
object = json_loadb (data, len, 0, &jerror);
if (!object) {
/* Perhaps the commit object contains invalid UTF-8 character. */
if (data[len-1] == 0)
clean_utf8_data (data, len - 1);
else
clean_utf8_data (data, len);
object = json_loadb (data, len, 0, &jerror);
if (!object) {
if (jerror.text)
seaf_warning ("Failed to load commit json object: %s.\n", jerror.text);
else
seaf_warning ("Failed to load commit json object.\n");
goto out;
}
}
commit = commit_from_json_object (commit_id, object);
if (commit)
commit->manager = mgr;
out:
if (object) json_decref (object);
g_free (data);
return commit;
}
static int
save_commit (SeafCommitManager *manager,
const char *repo_id,
int version,
SeafCommit *commit)
{
json_t *object = NULL;
char *data;
gsize len;
if (seaf_obj_store_obj_exists (manager->obj_store,
repo_id, version,
commit->commit_id))
return 0;
object = commit_to_json_object (commit);
data = json_dumps (object, 0);
len = strlen (data);
json_decref (object);
#ifdef SEAFILE_SERVER
if (seaf_obj_store_write_obj (manager->obj_store,
repo_id, version,
commit->commit_id,
data, (int)len, TRUE) < 0) {
g_free (data);
return -1;
}
#else
if (seaf_obj_store_write_obj (manager->obj_store,
repo_id, version,
commit->commit_id,
data, (int)len, FALSE) < 0) {
g_free (data);
return -1;
}
#endif
free (data);
return 0;
}
static void
delete_commit (SeafCommitManager *mgr,
const char *repo_id,
int version,
const char *id)
{
seaf_obj_store_delete_obj (mgr->obj_store, repo_id, version, id);
}
int
seaf_commit_manager_remove_store (SeafCommitManager *mgr,
const char *store_id)
{
return seaf_obj_store_remove_store (mgr->obj_store, store_id);
}
================================================
FILE: common/commit-mgr.h
================================================
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
#ifndef SEAF_COMMIT_MGR_H
#define SEAF_COMMIT_MGR_H
struct _SeafCommitManager;
typedef struct _SeafCommit SeafCommit;
#include <glib/gstdio.h>
#include "db.h"
#include "obj-store.h"
struct _SeafCommit {
struct _SeafCommitManager *manager;
int ref;
char commit_id[41];
char repo_id[37];
char root_id[41]; /* the fs root */
char *desc;
char *creator_name;
char creator_id[41];
guint64 ctime; /* creation time */
char *parent_id;
char *second_parent_id;
char *repo_name;
char *repo_desc;
char *repo_category;
char *device_name;
char *client_version;
gboolean encrypted;
int enc_version;
char *magic;
char *random_key;
char *salt;
char *pwd_hash;
char *pwd_hash_algo;
char *pwd_hash_params;
gboolean no_local_history;
int version;
gboolean new_merge;
gboolean conflict;
gboolean repaired;
};
/**
* @commit_id: if this is NULL, will create a new id.
* @ctime: if this is 0, will use current time.
*
* Any new commit should be added to commit manager before used.
*/
SeafCommit *
seaf_commit_new (const char *commit_id,
const char *repo_id,
const char *root_id,
const char *author_name,
const char *creator_id,
const char *desc,
guint64 ctime);
char *
seaf_commit_to_data (SeafCommit *commit, gsize *len);
SeafCommit *
seaf_commit_from_data (const char *id, char *data, gsize len);
void
seaf_commit_ref (SeafCommit *commit);
void
seaf_commit_unref (SeafCommit *commit);
/* Set stop to TRUE if you want to stop traversing a branch in the history graph.
Note, if currently there are multi branches, this function will be called again.
So, set stop to TRUE not always stop traversing the history graph.
*/
typedef gboolean (*CommitTraverseFunc) (SeafCommit *commit, void *data, gboolean *stop);
struct _SeafileSession;
typedef struct _SeafCommitManager SeafCommitManager;
typedef struct _SeafCommitManagerPriv SeafCommitManagerPriv;
struct _SeafCommitManager {
struct _SeafileSession *seaf;
sqlite3 *db;
struct SeafObjStore *obj_store;
SeafCommitManagerPriv *priv;
};
SeafCommitManager *
seaf_commit_manager_new (struct _SeafileSession *seaf);
int
seaf_commit_manager_init (SeafCommitManager *mgr);
/**
* Add a commit to commit manager and persist it to disk.
* Any new commit should be added to commit manager before used.
* This function increments ref count of the commit object.
* Not MT safe.
*/
int
seaf_commit_manager_add_commit (SeafCommitManager *mgr, SeafCommit *commit);
/**
* Delete a commit from commit manager and permanently remove it from disk.
* A commit object to be deleted should have ref cournt <= 1.
* Not MT safe.
*/
void
seaf_commit_manager_del_commit (SeafCommitManager *mgr,
const char *repo_id,
int version,
const char *id);
/**
* Find a commit object.
* This function increments ref count of returned object.
* Not MT safe.
*/
SeafCommit*
seaf_commit_manager_get_commit (SeafCommitManager *mgr,
const char *repo_id,
int version,
const char *id);
/**
* Get a commit object, with compatibility between version 0 and version 1.
* It will first try to get commit with version 1 layout; if fails, will
* try version 0 layout for compatibility.
* This is useful for loading a repo. In that case, we don't know the version
* of the repo before loading its head commit.
*/
SeafCommit *
seaf_commit_manager_get_commit_compatible (SeafCommitManager *mgr,
const char *repo_id,
const char *id);
/**
* Traverse the commits DAG start from head in topological order.
* The ordering is based on commit time.
* return FALSE if some commits is missing, TRUE otherwise.
*/
gboolean
seaf_commit_manager_traverse_commit_tree (SeafCommitManager *mgr,
const char *repo_id,
int version,
const char *head,
CommitTraverseFunc func,
void *data,
gboolean skip_errors);
/*
* The same as the above function, but stops traverse down if parent commit
* doesn't exists, instead of returning error.
*/
gboolean
seaf_commit_manager_traverse_commit_tree_truncated (SeafCommitManager *mgr,
const char *repo_id,
int version,
const char *head,
CommitTraverseFunc func,
void *data,
gboolean skip_errors);
/**
* Works the same as seaf_commit_manager_traverse_commit_tree, but stops
* traversing when a total number of _limit_ commits is reached. If
* limit <= 0, there is no limit
*/
gboolean
seaf_commit_manager_traverse_commit_tree_with_limit (SeafCommitManager *mgr,
const char *repo_id,
int version,
const char *head,
CommitTraverseFunc func,
int limit,
void *data,
char **next_start_commit,
gboolean skip_errors);
gboolean
seaf_commit_manager_commit_exists (SeafCommitManager *mgr,
const char *repo_id,
int version,
const char *id);
int
seaf_commit_manager_remove_store (SeafCommitManager *mgr,
const char *store_id);
#endif
================================================
FILE: common/common.h
================================================
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
#ifndef COMMON_H
#define COMMON_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h> /* uint32_t */
#include <sys/types.h> /* size_t */
#include <errno.h>
#include <string.h>
#include <limits.h>
#include <stdio.h>
#include <utime.h>
#include <glib.h>
#include <glib/gstdio.h>
#define EMPTY_SHA1 "0000000000000000000000000000000000000000"
#define CURRENT_ENC_VERSION 3
#define DEFAULT_PROTO_VERSION 1
#define CURRENT_PROTO_VERSION 7
#define CURRENT_REPO_VERSION 1
/* For compatibility with the old protocol, use an UUID for signature.
* Listen manager on the server will use the new block tx protocol if it
* receives this signature as "token".
*/
#define BLOCK_PROTOCOL_SIGNATURE "529319a0-577f-4d6b-a6c3-3c20f56f290c"
#define SEAF_PATH_MAX 4096
#ifndef ccnet_warning
#define ccnet_warning(fmt, ...) g_warning("%s(%d): " fmt, __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#ifndef ccnet_error
#define ccnet_error(fmt, ...) g_error("%s(%d): " fmt, __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#ifndef ccnet_message
#define ccnet_message(fmt, ...) g_message("%s(%d): " fmt, __FILE__, __LINE__, ##__VA_ARGS__)
#endif
#ifndef ccnet_debug
#define ccnet_debug(fmt, ...) g_debug(fmt, ##__VA_ARGS__)
#endif
#define DEFAULT_CONFIG_DIR "~/.ccnet"
#endif
================================================
FILE: common/config-mgr.c
================================================
#include "common.h"
#include "config-mgr.h"
#include "seaf-db.h"
#include "log.h"
int
seaf_cfg_manager_init (SeafCfgManager *mgr)
{
char *sql;
int db_type = seaf_db_type(mgr->db);
if (db_type == SEAF_DB_TYPE_MYSQL)
sql = "CREATE TABLE IF NOT EXISTS SeafileConf ("
"id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, cfg_group VARCHAR(255) NOT NULL,"
"cfg_key VARCHAR(255) NOT NULL, value VARCHAR(255), property INTEGER) ENGINE=INNODB";
else
sql = "CREATE TABLE IF NOT EXISTS SeafileConf (cfg_group VARCHAR(255) NOT NULL,"
"cfg_key VARCHAR(255) NOT NULL, value VARCHAR(255), property INTEGER)";
if (seaf_db_query (mgr->db, sql) < 0)
return -1;
return 0;
}
SeafCfgManager *
seaf_cfg_manager_new (SeafileSession *session)
{
SeafCfgManager *mgr = g_new0 (SeafCfgManager, 1);
if (!mgr)
return NULL;
mgr->config = session->config;
mgr->db = session->db;
return mgr;
}
int
seaf_cfg_manager_set_config_int (SeafCfgManager *mgr,
const char *group,
const char *key,
int value)
{
char value_str[256];
snprintf (value_str, sizeof(value_str), "%d", value);
return seaf_cfg_manager_set_config (mgr, group, key, value_str);
}
int
seaf_cfg_manager_set_config_int64 (SeafCfgManager *mgr,
const char *group,
const char *key,
gint64 value)
{
char value_str[256];
snprintf (value_str, sizeof(value_str), "%"G_GINT64_FORMAT"", value);
return seaf_cfg_manager_set_config (mgr, group, key, value_str);
}
int
seaf_cfg_manager_set_config_string (SeafCfgManager *mgr,
const char *group,
const char *key,
const char *value)
{
char value_str[256];
snprintf (value_str, sizeof(value_str), "%s", value);
return seaf_cfg_manager_set_config (mgr, group, key, value_str);
}
int
seaf_cfg_manager_set_config_boolean (SeafCfgManager *mgr,
const char *group,
const char *key,
gboolean value)
{
char value_str[256];
if (value)
snprintf (value_str, sizeof(value_str), "true");
else
snprintf (value_str, sizeof(value_str), "false");
return seaf_cfg_manager_set_config (mgr, group, key, value_str);
}
int
seaf_cfg_manager_set_config (SeafCfgManager *mgr, const char *group, const char *key, const char *value)
{
gboolean exists, err = FALSE;
char *sql = "SELECT 1 FROM SeafileConf WHERE cfg_group=? AND cfg_key=?";
exists = seaf_db_statement_exists(mgr->db, sql, &err,
2, "string", group,
"string", key);
if (err) {
seaf_warning ("[db error]Failed to set config [%s:%s] to db.\n", group, key);
return -1;
}
if (exists)
sql = "UPDATE SeafileConf SET value=? WHERE cfg_group=? AND cfg_key=?";
else
sql = "INSERT INTO SeafileConf (value, cfg_group, cfg_key, property) VALUES "
"(?,?,?,0)";
if (seaf_db_statement_query (mgr->db, sql, 3,
"string", value, "string",
group, "string", key) < 0) {
seaf_warning ("Failed to set config [%s:%s] to db.\n", group, key);
return -1;
}
return 0;
}
int
seaf_cfg_manager_get_config_int (SeafCfgManager *mgr, const char *group, const char *key)
{
int ret;
char *invalid = NULL;
char *value = seaf_cfg_manager_get_config (mgr, group, key);
if (!value) {
GError *err = NULL;
ret = g_key_file_get_integer (mgr->config, group, key, &err);
if (err) {
ret = -1;
g_clear_error(&err);
}
} else {
ret = strtol (value, &invalid, 10);
if (*invalid != '\0') {
ret = -1;
seaf_warning ("Value of config [%s:%s] is invalid: [%s]\n", group, key, value);
}
g_free (value);
}
return ret;
}
gint64
seaf_cfg_manager_get_config_int64 (SeafCfgManager *mgr, const char *group, const char *key)
{
gint64 ret;
char *invalid = NULL;
char *value = seaf_cfg_manager_get_config (mgr, group, key);
if (!value) {
GError *err = NULL;
ret = g_key_file_get_int64(mgr->config, group, key, &err);
if (err) {
ret = -1;
g_clear_error(&err);
}
} else {
ret = strtoll (value, &invalid, 10);
if (*invalid != '\0') {
seaf_warning ("Value of config [%s:%s] is invalid: [%s]\n", group, key, value);
ret = -1;
}
g_free (value);
}
return ret;
}
gboolean
seaf_cfg_manager_get_config_boolean (SeafCfgManager *mgr, const char *group, const char *key)
{
gboolean ret;
char *value = seaf_cfg_manager_get_config (mgr, group, key);
if (!value) {
GError *err = NULL;
ret = g_key_file_get_boolean(mgr->config, group, key, &err);
if (err) {
seaf_warning ("Config [%s:%s] not set, default is false.\n", group, key);
ret = FALSE;
g_clear_error(&err);
}
} else {
if (strcmp ("true", value) == 0)
ret = TRUE;
else
ret = FALSE;
g_free (value);
}
return ret;
}
char *
seaf_cfg_manager_get_config_string (SeafCfgManager *mgr, const char *group, const char *key)
{
char *ret = NULL;
char *value = seaf_cfg_manager_get_config (mgr, group, key);
if (!value) {
ret = g_key_file_get_string (mgr->config, group, key, NULL);
if (ret != NULL)
ret = g_strstrip(ret);
} else {
ret = value;
}
return ret;
}
char *
seaf_cfg_manager_get_config (SeafCfgManager *mgr, const char *group, const char *key)
{
char *sql = "SELECT value FROM SeafileConf WHERE cfg_group=? AND cfg_key=?";
char *value = seaf_db_statement_get_string(mgr->db, sql,
2, "string", group, "string", key);
if (value != NULL)
value = g_strstrip(value);
return value;
}
================================================
FILE: common/config-mgr.h
================================================
#ifndef SEAF_CONFIG_MGR_H
#define SEAF_CONFIG_MGR_H
typedef struct _SeafCfgManager SeafCfgManager;
#include "seafile-session.h"
struct _SeafCfgManager {
GKeyFile *config;
SeafDB *db;
};
typedef struct _SeafileSession SeafileSession;
SeafCfgManager *
seaf_cfg_manager_new (SeafileSession *seaf);
int
seaf_cfg_manager_set_config (SeafCfgManager *mgr, const char *group, const char *key, const char *value);
char *
seaf_cfg_manager_get_config (SeafCfgManager *mgr, const char *group, const char *key);
int
seaf_cfg_manager_set_config_int (SeafCfgManager *mgr, const char *group, const char *key, int value);
int
seaf_cfg_manager_get_config_int (SeafCfgManager *mgr, const char *group, const char *key);
int
seaf_cfg_manager_set_config_int64 (SeafCfgManager *mgr, const char *group, const char *key, gint64 value);
gint64
seaf_cfg_manager_get_config_int64 (SeafCfgManager *mgr, const char *group, const char *key);
int
seaf_cfg_manager_set_config_string (SeafCfgManager *mgr, const char *group, const char *key, const char *value);
char *
seaf_cfg_manager_get_config_string (SeafCfgManager *mgr, const char *group, const char *key);
int
seaf_cfg_manager_set_config_boolean (SeafCfgManager *mgr, const char *group, const char *key, gboolean value);
gboolean
seaf_cfg_manager_get_config_boolean (SeafCfgManager *mgr, const char *group, const char *key);
int
seaf_cfg_manager_init (SeafCfgManager *mgr);
#endif /* SEAF_CONFIG_MGR_H */
================================================
FILE: common/diff-simple.c
================================================
#include "common.h"
#include "diff-simple.h"
#include "utils.h"
#include "log.h"
DiffEntry *
diff_entry_new (char type, char status, unsigned char *sha1, const char *name)
{
DiffEntry *de = g_new0 (DiffEntry, 1);
de->type = type;
de->status = status;
memcpy (de->sha1, sha1, 20);
de->name = g_strdup(name);
return de;
}
DiffEntry *
diff_entry_new_from_dirent (char type, char status,
SeafDirent *dent, const char *basedir)
{
DiffEntry *de = g_new0 (DiffEntry, 1);
unsigned char sha1[20];
char *path;
hex_to_rawdata (dent->id, sha1, 20);
path = g_strconcat (basedir, dent->name, NULL);
de->type = type;
de->status = status;
memcpy (de->sha1, sha1, 20);
de->name = path;
de->size = dent->size;
#ifdef SEAFILE_CLIENT
if (type == DIFF_TYPE_COMMITS &&
(status == DIFF_STATUS_ADDED ||
status == DIFF_STATUS_MODIFIED ||
status == DIFF_STATUS_DIR_ADDED ||
status == DIFF_STATUS_DIR_DELETED)) {
de->mtime = dent->mtime;
de->mode = dent->mode;
de->modifier = g_strdup(dent->modifier);
}
#endif
return de;
}
void
diff_entry_free (DiffEntry *de)
{
g_free (de->name);
if (de->new_name)
g_free (de->new_name);
#ifdef SEAFILE_CLIENT
g_free (de->modifier);
#endif
g_free (de);
}
inline static gboolean
dirent_same (SeafDirent *denta, SeafDirent *dentb)
{
return (strcmp (dentb->id, denta->id) == 0 &&
denta->mode == dentb->mode &&
denta->mtime == dentb->mtime);
}
static int
diff_files (int n, SeafDirent *dents[], const char *basedir, DiffOptions *opt)
{
SeafDirent *files[3];
int i, n_files = 0;
memset (files, 0, sizeof(files[0])*n);
for (i = 0; i < n; ++i) {
if (dents[i] && S_ISREG(dents[i]->mode)) {
files[i] = dents[i];
++n_files;
}
}
if (n_files == 0)
return 0;
return opt->file_cb (n, basedir, files, opt->data);
}
static int
diff_trees_recursive (int n, SeafDir *trees[],
const char *basedir, DiffOptions *opt);
static int
diff_directories (int n, SeafDirent *dents[], const char *basedir, DiffOptions *opt)
{
SeafDirent *dirs[3];
int i, n_dirs = 0;
char *dirname = "";
int ret;
SeafDir *sub_dirs[3], *dir;
memset (dirs, 0, sizeof(dirs[0])*n);
for (i = 0; i < n; ++i) {
if (dents[i] && S_ISDIR(dents[i]->mode)) {
dirs[i] = dents[i];
++n_dirs;
}
}
if (n_dirs == 0)
return 0;
gboolean recurse = TRUE;
ret = opt->dir_cb (n, basedir, dirs, opt->data, &recurse);
if (ret < 0)
return ret;
if (!recurse)
return 0;
memset (sub_dirs, 0, sizeof(sub_dirs[0])*n);
for (i = 0; i < n; ++i) {
if (dents[i] != NULL && S_ISDIR(dents[i]->mode)) {
dir = seaf_fs_manager_get_seafdir (seaf->fs_mgr,
opt->store_id,
opt->version,
dents[i]->id);
if (!dir) {
seaf_warning ("Failed to find dir %s:%s.\n",
opt->store_id, dents[i]->id);
ret = -1;
goto free_sub_dirs;
}
sub_dirs[i] = dir;
dirname = dents[i]->name;
}
}
char *new_basedir = g_strconcat (basedir, dirname, "/", NULL);
ret = diff_trees_recursive (n, sub_dirs, new_basedir, opt);
g_free (new_basedir);
free_sub_dirs:
for (i = 0; i < n; ++i)
seaf_dir_free (sub_dirs[i]);
return ret;
}
static int
diff_trees_recursive (int n, SeafDir *trees[],
const char *basedir, DiffOptions *opt)
{
GList *ptrs[3];
SeafDirent *dents[3];
int i;
SeafDirent *dent;
char *first_name;
gboolean done;
int ret = 0;
for (i = 0; i < n; ++i) {
if (trees[i])
ptrs[i] = trees[i]->entries;
else
ptrs[i] = NULL;
}
while (1) {
first_name = NULL;
memset (dents, 0, sizeof(dents[0])*n);
done = TRUE;
/* Find the "largest" name, assuming dirents are sorted. */
for (i = 0; i < n; ++i) {
if (ptrs[i] != NULL) {
done = FALSE;
dent = ptrs[i]->data;
if (!first_name)
first_name = dent->name;
else if (strcmp(dent->name, first_name) > 0)
first_name = dent->name;
}
}
if (done)
break;
/*
* Setup dir entries for all names that equal to first_name
*/
for (i = 0; i < n; ++i) {
if (ptrs[i] != NULL) {
dent = ptrs[i]->data;
if (strcmp(first_name, dent->name) == 0) {
dents[i] = dent;
ptrs[i] = ptrs[i]->next;
}
}
}
if (n == 2 && dents[0] && dents[1] && dirent_same(dents[0], dents[1]))
continue;
if (n == 3 && dents[0] && dents[1] && dents[2] &&
dirent_same(dents[0], dents[1]) && dirent_same(dents[0], dents[2]))
continue;
/* Diff files of this level. */
ret = diff_files (n, dents, basedir, opt);
if (ret < 0)
return ret;
/* Recurse into sub level. */
ret = diff_directories (n, dents, basedir, opt);
if (ret < 0)
return ret;
}
return ret;
}
int
diff_trees (int n, const char *roots[], DiffOptions *opt)
{
SeafDir **trees, *root;
int i, ret;
g_return_val_if_fail (n == 2 || n == 3, -1);
trees = g_new0 (SeafDir *, n);
for (i = 0; i < n; ++i) {
root = seaf_fs_manager_get_seafdir (seaf->fs_mgr,
opt->store_id,
opt->version,
roots[i]);
if (!root) {
seaf_warning ("Failed to find dir %s:%s.\n", opt->store_id, roots[i]);
g_free (trees);
return -1;
}
trees[i] = root;
}
ret = diff_trees_recursive (n, trees, "", opt);
for (i = 0; i < n; ++i)
seaf_dir_free (trees[i]);
g_free (trees);
return ret;
}
typedef struct DiffData {
GList **results;
gboolean fold_dir_diff;
} DiffData;
static int
twoway_diff_files (int n, const char *basedir, SeafDirent *files[], void *vdata)
{
DiffData *data = vdata;
GList **results = data->results;
DiffEntry *de;
SeafDirent *tree1 = files[0];
SeafDirent *tree2 = files[1];
if (!tree1) {
de = diff_entry_new_from_dirent (DIFF_TYPE_COMMITS, DIFF_STATUS_ADDED,
tree2, basedir);
*results = g_list_prepend (*results, de);
return 0;
}
if (!tree2) {
de = diff_entry_new_from_dirent (DIFF_TYPE_COMMITS, DIFF_STATUS_DELETED,
tree1, basedir);
*results = g_list_prepend (*results, de);
return 0;
}
if (!dirent_same (tree1, tree2)) {
de = diff_entry_new_from_dirent (DIFF_TYPE_COMMITS, DIFF_STATUS_MODIFIED,
tree2, basedir);
de->origin_size = tree1->size;
*results = g_list_prepend (*results, de);
}
return 0;
}
static int
twoway_diff_dirs (int n, const char *basedir, SeafDirent *dirs[], void *vdata,
gboolean *recurse)
{
DiffData *data = vdata;
GList **results = data->results;
DiffEntry *de;
SeafDirent *tree1 = dirs[0];
SeafDirent *tree2 = dirs[1];
if (!tree1) {
if (strcmp (tree2->id, EMPTY_SHA1) == 0 || data->fold_dir_diff) {
de = diff_entry_new_from_dirent (DIFF_TYPE_COMMITS, DIFF_STATUS_DIR_ADDED,
tree2, basedir);
*results = g_list_prepend (*results, de);
*recurse = FALSE;
} else
*recurse = TRUE;
return 0;
}
if (!tree2) {
de = diff_entry_new_from_dirent (DIFF_TYPE_COMMITS,
DIFF_STATUS_DIR_DELETED,
tree1, basedir);
*results = g_list_prepend (*results, de);
if (data->fold_dir_diff) {
*recurse = FALSE;
} else
*recurse = TRUE;
return 0;
}
return 0;
}
int
d
gitextract_lx6ttehu/ ├── .github/ │ └── workflows/ │ ├── ci.yml │ └── golangci-lint.yml ├── .gitignore ├── LICENSE.txt ├── Makefile.am ├── README.markdown ├── README.testing.md ├── autogen.sh ├── ci/ │ ├── install-deps.sh │ ├── requirements.txt │ ├── run.py │ ├── serverctl.py │ └── utils.py ├── common/ │ ├── Makefile.am │ ├── block-backend-fs.c │ ├── block-backend.c │ ├── block-backend.h │ ├── block-mgr.c │ ├── block-mgr.h │ ├── block-tx-utils.c │ ├── block-tx-utils.h │ ├── block.h │ ├── branch-mgr.c │ ├── branch-mgr.h │ ├── cdc/ │ │ ├── Makefile.am │ │ ├── cdc.c │ │ ├── cdc.h │ │ ├── rabin-checksum.c │ │ └── rabin-checksum.h │ ├── commit-mgr.c │ ├── commit-mgr.h │ ├── common.h │ ├── config-mgr.c │ ├── config-mgr.h │ ├── diff-simple.c │ ├── diff-simple.h │ ├── fs-mgr.c │ ├── fs-mgr.h │ ├── group-mgr.c │ ├── group-mgr.h │ ├── log.c │ ├── log.h │ ├── merge-new.c │ ├── merge-new.h │ ├── mq-mgr.c │ ├── mq-mgr.h │ ├── obj-backend-fs.c │ ├── obj-backend-riak.c │ ├── obj-backend.h │ ├── obj-cache.c │ ├── obj-cache.h │ ├── obj-store.c │ ├── obj-store.h │ ├── object-list.c │ ├── object-list.h │ ├── org-mgr.c │ ├── org-mgr.h │ ├── password-hash.c │ ├── password-hash.h │ ├── processors/ │ │ └── objecttx-common.h │ ├── redis-cache.c │ ├── redis-cache.h │ ├── rpc-service.c │ ├── seaf-db.c │ ├── seaf-db.h │ ├── seaf-utils.c │ ├── seaf-utils.h │ ├── seafile-crypt.c │ ├── seafile-crypt.h │ ├── sync-repo-common.h │ ├── user-mgr.c │ ├── user-mgr.h │ ├── vc-common.c │ └── vc-common.h ├── configure.ac ├── controller/ │ ├── Makefile.am │ ├── seafile-controller.c │ └── seafile-controller.h ├── doc/ │ └── Makefile.am ├── fileserver/ │ ├── .golangci.yml │ ├── blockmgr/ │ │ ├── blockmgr.go │ │ └── blockmgr_test.go │ ├── commitmgr/ │ │ ├── commitmgr.go │ │ ├── commitmgr_test.go │ │ └── null.go │ ├── crypt.go │ ├── diff/ │ │ ├── diff.go │ │ └── diff_test.go │ ├── fileop.go │ ├── fileserver.go │ ├── fsmgr/ │ │ ├── fsmgr.go │ │ └── fsmgr_test.go │ ├── go.mod │ ├── go.sum │ ├── http_code.go │ ├── merge.go │ ├── merge_test.go │ ├── metrics/ │ │ └── metrics.go │ ├── objstore/ │ │ ├── backend_fs.go │ │ ├── objstore.go │ │ └── objstore_test.go │ ├── option/ │ │ └── option.go │ ├── quota.go │ ├── repomgr/ │ │ ├── repomgr.go │ │ └── repomgr_test.go │ ├── searpc/ │ │ ├── searpc.go │ │ └── searpc_test.go │ ├── share/ │ │ ├── group/ │ │ │ └── group.go │ │ ├── public/ │ │ │ └── public.go │ │ └── share.go │ ├── size_sched.go │ ├── sync_api.go │ ├── utils/ │ │ ├── dup2.go │ │ ├── dup3.go │ │ ├── http.go │ │ └── utils.go │ ├── virtual_repo.go │ └── workerpool/ │ └── workerpool.go ├── fuse/ │ ├── Makefile.am │ ├── file.c │ ├── getattr.c │ ├── readdir.c │ ├── repo-mgr.c │ ├── repo-mgr.h │ ├── seaf-fuse.c │ ├── seaf-fuse.h │ ├── seafile-session.c │ └── seafile-session.h ├── include/ │ ├── Makefile.am │ ├── seafile-error.h │ └── seafile-rpc.h ├── lib/ │ ├── Makefile.am │ ├── bloom-filter.c │ ├── bloom-filter.h │ ├── branch.vala │ ├── ccnetobj.vala │ ├── commit.vala │ ├── copy-task.vala │ ├── crypt.vala │ ├── db.c │ ├── db.h │ ├── dir.vala │ ├── dirent.vala │ ├── file.vala │ ├── include.h │ ├── job-mgr.c │ ├── job-mgr.h │ ├── libseafile.pc.in │ ├── net.c │ ├── net.h │ ├── repo.vala │ ├── rpc_table.py │ ├── seahub.vala │ ├── search-result.vala │ ├── task.vala │ ├── timer.c │ ├── timer.h │ ├── utils.c │ ├── utils.h │ └── webaccess.vala ├── m4/ │ ├── ax_lib_sqlite3.m4 │ ├── glib-gettext.m4 │ └── python.m4 ├── notification-server/ │ ├── .golangci.yml │ ├── ccnet.conf │ ├── client.go │ ├── dup2.go │ ├── dup3.go │ ├── event.go │ ├── go.mod │ ├── go.sum │ ├── logger.go │ ├── server.go │ └── subscriptions.go ├── pytest.ini ├── python/ │ ├── LICENSE.txt │ ├── Makefile.am │ ├── seafile/ │ │ ├── Makefile.am │ │ ├── __init__.py │ │ └── rpcclient.py │ └── seaserv/ │ ├── Makefile.am │ ├── __init__.py │ ├── api.py │ └── service.py ├── run_tests.sh ├── scripts/ │ ├── Makefile.am │ ├── parse_seahub_db.py │ └── sql/ │ ├── mysql/ │ │ ├── ccnet.sql │ │ └── seafile.sql │ └── sqlite/ │ ├── config.sql │ ├── groupmgr.sql │ ├── org.sql │ ├── seafile.sql │ └── user.sql ├── server/ │ ├── Makefile.am │ ├── access-file.c │ ├── access-file.h │ ├── change-set.c │ ├── change-set.h │ ├── copy-mgr.c │ ├── copy-mgr.h │ ├── fileserver-config.c │ ├── fileserver-config.h │ ├── gc/ │ │ ├── Makefile.am │ │ ├── fsck.c │ │ ├── fsck.h │ │ ├── gc-core.c │ │ ├── gc-core.h │ │ ├── repo-mgr.c │ │ ├── repo-mgr.h │ │ ├── seaf-fsck.c │ │ ├── seafile-session.c │ │ ├── seafile-session.h │ │ ├── seafserv-gc.c │ │ ├── verify.c │ │ └── verify.h │ ├── http-server.c │ ├── http-server.h │ ├── http-status-codes.h │ ├── http-tx-mgr.c │ ├── http-tx-mgr.h │ ├── index-blocks-mgr.c │ ├── index-blocks-mgr.h │ ├── metric-mgr.c │ ├── metric-mgr.h │ ├── notif-mgr.c │ ├── notif-mgr.h │ ├── pack-dir.c │ ├── pack-dir.h │ ├── passwd-mgr.c │ ├── passwd-mgr.h │ ├── permission-mgr.c │ ├── permission-mgr.h │ ├── quota-mgr.c │ ├── quota-mgr.h │ ├── repo-mgr.c │ ├── repo-mgr.h │ ├── repo-op.c │ ├── repo-perm.c │ ├── seaf-server.c │ ├── seafile-session.c │ ├── seafile-session.h │ ├── share-mgr.c │ ├── share-mgr.h │ ├── size-sched.c │ ├── size-sched.h │ ├── upload-file.c │ ├── upload-file.h │ ├── virtual-repo.c │ ├── web-accesstoken-mgr.c │ ├── web-accesstoken-mgr.h │ ├── zip-download-mgr.c │ └── zip-download-mgr.h ├── tests/ │ ├── __init__.py │ ├── conf/ │ │ ├── ccnet.conf │ │ └── mykey.peer │ ├── config.py │ ├── conftest.py │ ├── test_file_operation/ │ │ ├── test_file_operation.py │ │ ├── test_merge_virtual_repo.py │ │ ├── test_search_files.py │ │ ├── test_upload_and_update.py │ │ ├── test_upload_large_files.py │ │ └── test_zip_download.py │ ├── test_file_property_and_dir_listing/ │ │ └── test_file_property_and_dir_listing.py │ ├── test_gc/ │ │ └── test_gc.py │ ├── test_get_repo_list/ │ │ └── test_get_repo_list.py │ ├── test_group/ │ │ └── test_groups.py │ ├── test_password/ │ │ └── test_password.py │ ├── test_repo_manipulation/ │ │ └── test_repo_manipulation.py │ ├── test_server_config/ │ │ └── test_server_config.py │ ├── test_share_and_perm/ │ │ ├── test_shared_repo_perm.py │ │ └── test_structure_repo_perm.py │ ├── test_trashed_repos/ │ │ └── test_trashed_repos.py │ ├── test_upload/ │ │ ├── account.conf │ │ ├── go.mod │ │ ├── go.sum │ │ ├── readme.md │ │ └── test_upload.go │ ├── test_user/ │ │ └── test_users.py │ └── utils.py ├── tools/ │ ├── Makefile.am │ └── seafile-admin └── updateversion.sh
Showing preview only (251K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (3546 symbols across 205 files)
FILE: ci/run.py
function num_jobs (line 36) | def num_jobs():
function make_build_env (line 41) | def make_build_env():
function prepend_env_value (line 81) | def prepend_env_value(name, value, seperator=':', env=None):
function get_branch_json_file (line 94) | def get_branch_json_file():
function get_project_branch (line 99) | def get_project_branch(project, default_branch='master'):
class Project (line 107) | class Project(object):
method __init__ (line 108) | def __init__(self, name):
method url (line 113) | def url(self):
method projectdir (line 117) | def projectdir(self):
method branch (line 120) | def branch(self):
method clone (line 123) | def clone(self):
method compile_and_install (line 134) | def compile_and_install(self):
method use_branch (line 145) | def use_branch(self, branch):
class Libsearpc (line 149) | class Libsearpc(Project):
method __init__ (line 150) | def __init__(self):
method branch (line 153) | def branch(self):
class CcnetServer (line 157) | class CcnetServer(Project):
method __init__ (line 158) | def __init__(self):
method branch (line 161) | def branch(self):
class SeafileServer (line 165) | class SeafileServer(Project):
method __init__ (line 166) | def __init__(self):
class Libevhtp (line 169) | class Libevhtp(Project):
method __init__ (line 170) | def __init__(self):
method branch (line 173) | def branch(self):
method compile_and_install (line 177) | def compile_and_install(self):
class Libjwt (line 188) | class Libjwt(Project):
method __init__ (line 189) | def __init__(self):
method branch (line 192) | def branch(self):
method url (line 196) | def url(self):
method compile_and_install (line 200) | def compile_and_install(self):
class Libhiredis (line 211) | class Libhiredis(Project):
method __init__ (line 212) | def __init__(self):
method branch (line 215) | def branch(self):
method url (line 219) | def url(self):
method compile_and_install (line 223) | def compile_and_install(self):
function fetch_and_build (line 232) | def fetch_and_build():
function parse_args (line 253) | def parse_args():
function main (line 261) | def main():
function start_and_test_with_db (line 272) | def start_and_test_with_db(db):
FILE: ci/serverctl.py
class ServerCtl (line 24) | class ServerCtl(object):
method __init__ (line 25) | def __init__(self, topdir, projectdir, datadir, fileserver, db='sqlite...
method setup (line 50) | def setup(self):
method init_seafile (line 60) | def init_seafile(self):
method add_seafile_sqlite_db_conf (line 82) | def add_seafile_sqlite_db_conf(self):
method add_seafile_db_conf (line 91) | def add_seafile_db_conf(self):
method run (line 108) | def run(self):
method print_logs (line 118) | def print_logs(self):
method wait_ccnet_ready (line 124) | def wait_ccnet_ready(self):
method start (line 128) | def start(self):
method create_database_tables (line 135) | def create_database_tables(self):
method start_ccnet (line 174) | def start_ccnet(self):
method start_seafile (line 186) | def start_seafile(self):
method start_fileserver (line 201) | def start_fileserver(self):
method stop (line 217) | def stop(self):
method get_seaserv_envs (line 230) | def get_seaserv_envs(self):
function create_mysql_dbs (line 241) | def create_mysql_dbs():
function del_mysql_dbs (line 254) | def del_mysql_dbs():
FILE: ci/utils.py
function _color (line 22) | def _color(s, color):
function green (line 27) | def green(s):
function red (line 31) | def red(s):
function debug (line 35) | def debug(fmt, *a):
function info (line 39) | def info(fmt, *a):
function warning (line 43) | def warning(fmt, *a):
function shell (line 47) | def shell(cmd, inputdata=None, wait=True, **kw):
function cd (line 63) | def cd(path):
function chdir (line 72) | def chdir(func):
function setup_logging (line 80) | def setup_logging():
function mkdirs (line 93) | def mkdirs(*paths):
function on_github_actions (line 98) | def on_github_actions():
function cd (line 102) | def cd(path):
FILE: common/block-backend-fs.c
type _BHandle (line 21) | struct _BHandle {
type FsPriv (line 30) | typedef struct {
function BHandle (line 49) | static BHandle *
function block_backend_fs_read_block (line 95) | static int
function block_backend_fs_write_block (line 110) | static int
function block_backend_fs_close_block (line 125) | static int
function block_backend_fs_block_handle_free (line 136) | static void
function create_parent_path (line 149) | static int
function block_backend_fs_commit_block (line 171) | static int
function gboolean (line 196) | static gboolean
function block_backend_fs_remove_block (line 211) | static int
function BMetadata (line 224) | static BMetadata *
function BMetadata (line 247) | static BMetadata *
function block_backend_fs_foreach_block (line 266) | static int
function block_backend_fs_copy (line 325) | static int
function block_backend_fs_remove_store (line 366) | static int
function open_tmp_file (line 443) | static int
function BlockBackend (line 459) | BlockBackend *
FILE: common/block-backend.c
function BlockBackend (line 11) | BlockBackend*
function BlockBackend (line 37) | BlockBackend*
FILE: common/block-backend.h
type BlockBackend (line 8) | typedef struct BlockBackend BlockBackend;
type BlockBackend (line 10) | struct BlockBackend {
FILE: common/block-mgr.c
function SeafBlockManager (line 29) | SeafBlockManager *
function seaf_block_manager_init (line 52) | int
function BlockHandle (line 59) | BlockHandle *
function seaf_block_manager_read_block (line 75) | int
function seaf_block_manager_write_block (line 83) | int
function seaf_block_manager_close_block (line 91) | int
function seaf_block_manager_block_handle_free (line 98) | void
function seaf_block_manager_commit_block (line 105) | int
function gboolean (line 112) | gboolean seaf_block_manager_block_exists (SeafBlockManager *mgr,
function seaf_block_manager_remove_block (line 124) | int
function BlockMetadata (line 137) | BlockMetadata *
function BlockMetadata (line 150) | BlockMetadata *
function seaf_block_manager_foreach_block (line 157) | int
function seaf_block_manager_copy_block (line 169) | int
function gboolean (line 191) | static gboolean
function guint64 (line 204) | guint64
function gboolean (line 217) | gboolean
function seaf_block_manager_remove_store (line 266) | int
FILE: common/block-mgr.h
type _SeafileSession (line 12) | struct _SeafileSession
type SeafBlockManager (line 14) | typedef struct _SeafBlockManager SeafBlockManager;
type _SeafBlockManager (line 16) | struct _SeafBlockManager {
type _SeafileSession (line 24) | struct _SeafileSession
FILE: common/block-tx-utils.c
function blocktx_generate_encrypt_key (line 12) | void
function blocktx_encrypt_init (line 26) | int
function blocktx_decrypt_init (line 47) | int
function send_encrypted_data_frame_begin (line 70) | int
function send_encrypted_data (line 91) | int
function send_encrypted_data_frame_end (line 115) | int
function handle_frame_content (line 137) | static int
function handle_one_frame (line 187) | int
function handle_frame_fragment_content (line 210) | static int
function handle_frame_fragments (line 268) | int
FILE: common/block-tx-utils.h
type _HandshakeRequest (line 25) | struct _HandshakeRequest {
type HandshakeRequest (line 31) | typedef struct _HandshakeRequest HandshakeRequest;
type _HandshakeResponse (line 33) | struct _HandshakeResponse {
type HandshakeResponse (line 38) | typedef struct _HandshakeResponse HandshakeResponse;
type _AuthResponse (line 40) | struct _AuthResponse {
type AuthResponse (line 44) | typedef struct _AuthResponse AuthResponse;
type _RequestHeader (line 51) | struct _RequestHeader {
type RequestHeader (line 56) | typedef struct _RequestHeader RequestHeader;
type _ResponseHeader (line 58) | struct _ResponseHeader {
type ResponseHeader (line 62) | typedef struct _ResponseHeader ResponseHeader;
type FrameParser (line 109) | typedef struct _FrameParser {
type evbuffer (line 134) | struct evbuffer
type evbuffer (line 140) | struct evbuffer
FILE: common/block.h
type BlockMetadata (line 6) | typedef struct _BMetadata BlockMetadata;
type BMetadata (line 7) | typedef struct _BMetadata BMetadata;
type _BMetadata (line 9) | struct _BMetadata {
type BlockHandle (line 16) | typedef struct _BHandle BlockHandle;
type BHandle (line 17) | typedef struct _BHandle BHandle;
type gboolean (line 24) | typedef gboolean (*SeafBlockFunc) (const char *store_id,
FILE: common/branch-mgr.c
function SeafBranch (line 21) | SeafBranch *
function seaf_branch_free (line 39) | void
function seaf_branch_list_free (line 47) | void
function seaf_branch_set_commit (line 59) | void
function seaf_branch_ref (line 66) | void
function seaf_branch_unref (line 72) | void
type _SeafBranchManagerPriv (line 82) | struct _SeafBranchManagerPriv {
function SeafBranchManager (line 91) | SeafBranchManager *
function seaf_branch_manager_init (line 107) | int
function open_db (line 113) | static int
function seaf_branch_manager_add_branch (line 173) | int
function seaf_branch_manager_del_branch (line 242) | int
function seaf_branch_manager_update_branch (line 271) | int
function gboolean (line 307) | static gboolean
function publish_repo_update_event (line 320) | static void
function notify_repo_update (line 337) | static void
function on_branch_updated (line 363) | static void
function gboolean (line 378) | static gboolean
function seaf_branch_manager_test_and_update_branch (line 388) | int
function SeafBranch (line 495) | static SeafBranch *
function SeafBranch (line 539) | SeafBranch *
function gboolean (line 560) | static gboolean
function SeafBranch (line 572) | static SeafBranch *
function SeafBranch (line 595) | SeafBranch *
function gboolean (line 613) | gboolean
function GList (line 642) | GList *
function gboolean (line 692) | static gboolean
function GList (line 711) | GList *
FILE: common/branch-mgr.h
type SeafBranch (line 7) | typedef struct _SeafBranch SeafBranch;
type _SeafBranch (line 9) | struct _SeafBranch {
type SeafBranchManager (line 26) | typedef struct _SeafBranchManager SeafBranchManager;
type SeafBranchManagerPriv (line 27) | typedef struct _SeafBranchManagerPriv SeafBranchManagerPriv;
type _SeafileSession (line 29) | struct _SeafileSession
type _SeafBranchManager (line 30) | struct _SeafBranchManager {
type _SeafileSession (line 36) | struct _SeafileSession
FILE: common/cdc/cdc.c
function default_write_chunk (line 38) | static int default_write_chunk (CDCDescriptor *chunk_descr)
function init_cdc_file_descriptor (line 56) | static int init_cdc_file_descriptor (int fd,
function file_chunk_cdc (line 112) | int file_chunk_cdc(int fd_src,
function filename_chunk_cdc (line 231) | int filename_chunk_cdc(const char *filename,
function cdc_init (line 248) | void cdc_init ()
FILE: common/cdc/cdc.h
type _CDCFileDescriptor (line 23) | struct _CDCFileDescriptor
type _CDCDescriptor (line 24) | struct _CDCDescriptor
type SeafileCrypt (line 25) | struct SeafileCrypt
type _CDCDescriptor (line 29) | struct _CDCDescriptor
type SeafileCrypt (line 30) | struct SeafileCrypt
type CDCFileDescriptor (line 35) | typedef struct _CDCFileDescriptor {
type CDCDescriptor (line 52) | typedef struct _CDCDescriptor {
type SeafileCrypt (line 62) | struct SeafileCrypt
type SeafileCrypt (line 68) | struct SeafileCrypt
FILE: common/cdc/rabin-checksum.c
type u_int (line 7) | typedef unsigned int u_int;
type u_char (line 11) | typedef unsigned char u_char;
type u_short (line 15) | typedef unsigned short u_short;
type u_long (line 19) | typedef unsigned long u_long;
type u_int16_t (line 23) | typedef uint16_t u_int16_t;
type u_int32_t (line 27) | typedef uint32_t u_int32_t;
type u_int64_t (line 31) | typedef uint64_t u_int64_t;
function u_int (line 59) | static inline u_int fls32 (u_int32_t v)
function fls64 (line 73) | static inline char fls64 (u_int64_t v)
function u_int64_t (line 82) | u_int64_t polymod (u_int64_t nh, u_int64_t nl, u_int64_t d)
function polymult (line 107) | void polymult (u_int64_t *php, u_int64_t *plp, u_int64_t x, u_int64_t y)
function u_int64_t (line 124) | u_int64_t polymmult (u_int64_t x, u_int64_t y, u_int64_t d)
function u_int64_t (line 131) | static u_int64_t append8 (u_int64_t p, u_char m)
function calcT (line 136) | static void calcT (u_int64_t poly)
function calcU (line 147) | static void calcU(int size)
function rabin_init (line 157) | void rabin_init(int len)
function rabin_checksum (line 166) | unsigned int rabin_checksum(char *buf, int len)
function rabin_rolling_checksum (line 176) | unsigned int rabin_rolling_checksum(unsigned int csum, int len,
FILE: common/commit-mgr.c
type _SeafCommitManagerPriv (line 20) | struct _SeafCommitManagerPriv {
function compute_commit_id (line 41) | static void compute_commit_id (SeafCommit* commit)
function SeafCommit (line 62) | SeafCommit*
function SeafCommit (line 126) | SeafCommit *
function seaf_commit_free (line 158) | static void
function seaf_commit_ref (line 179) | void
function seaf_commit_unref (line 185) | void
function SeafCommitManager (line 195) | SeafCommitManager*
function seaf_commit_manager_init (line 207) | int
function add_commit_to_cache (line 218) | inline static void
function remove_commit_from_cache (line 227) | inline static void
function seaf_commit_manager_add_commit (line 235) | int
function seaf_commit_manager_del_commit (line 248) | void
function SeafCommit (line 274) | SeafCommit*
function SeafCommit (line 299) | SeafCommit *
function gint (line 318) | static gint
function insert_parent_commit (line 328) | inline static int
function gboolean (line 359) | gboolean
function gboolean (line 467) | static gboolean
function gboolean (line 561) | gboolean
function gboolean (line 574) | gboolean
function gboolean (line 587) | gboolean
function json_t (line 602) | static json_t *
function SeafCommit (line 666) | static SeafCommit *
function SeafCommit (line 841) | static SeafCommit *
function save_commit (line 889) | static int
function delete_commit (line 933) | static void
function seaf_commit_manager_remove_store (line 942) | int
FILE: common/commit-mgr.h
type _SeafCommitManager (line 6) | struct _SeafCommitManager
type SeafCommit (line 7) | typedef struct _SeafCommit SeafCommit;
type _SeafCommit (line 14) | struct _SeafCommit {
type gboolean (line 82) | typedef gboolean (*CommitTraverseFunc) (SeafCommit *commit, void *data, ...
type _SeafileSession (line 84) | struct _SeafileSession
type SeafCommitManager (line 86) | typedef struct _SeafCommitManager SeafCommitManager;
type SeafCommitManagerPriv (line 87) | typedef struct _SeafCommitManagerPriv SeafCommitManagerPriv;
type _SeafCommitManager (line 89) | struct _SeafCommitManager {
type _SeafileSession (line 99) | struct _SeafileSession
FILE: common/config-mgr.c
function seaf_cfg_manager_init (line 6) | int
function SeafCfgManager (line 26) | SeafCfgManager *
function seaf_cfg_manager_set_config_int (line 39) | int
function seaf_cfg_manager_set_config_int64 (line 52) | int
function seaf_cfg_manager_set_config_string (line 65) | int
function seaf_cfg_manager_set_config_boolean (line 78) | int
function seaf_cfg_manager_set_config (line 94) | int
function seaf_cfg_manager_get_config_int (line 122) | int
function gint64 (line 148) | gint64
function gboolean (line 174) | gboolean
FILE: common/config-mgr.h
type SeafCfgManager (line 4) | typedef struct _SeafCfgManager SeafCfgManager;
type _SeafCfgManager (line 7) | struct _SeafCfgManager {
type SeafileSession (line 12) | typedef struct _SeafileSession SeafileSession;
FILE: common/diff-simple.c
function DiffEntry (line 6) | DiffEntry *
function DiffEntry (line 19) | DiffEntry *
function diff_entry_free (line 51) | void
function gboolean (line 65) | inline static gboolean
function diff_files (line 73) | static int
function diff_directories (line 97) | static int
function diff_trees_recursive (line 156) | static int
function diff_trees (line 229) | int
type DiffData (line 260) | typedef struct DiffData {
function twoway_diff_files (line 265) | static int
function twoway_diff_dirs (line 298) | static int
function diff_commits (line 335) | int
function diff_commit_roots (line 378) | int
function threeway_diff_files (line 407) | static int
function threeway_diff_dirs (line 454) | static int
function diff_merge (line 462) | int
function diff_merge_roots (line 534) | int
function diff_resolve_renames (line 570) | void
function gboolean (line 695) | static gboolean
function diff_resolve_empty_dirs (line 727) | void
function diff_unmerged_state (line 755) | int diff_unmerged_state(int mask)
FILE: common/diff-simple.h
type DiffEntry (line 36) | typedef struct DiffEntry {
type DiffOptions (line 102) | typedef struct DiffOptions {
FILE: common/fs-mgr.c
type _SeafFSManagerPriv (line 40) | struct _SeafFSManagerPriv {
type SeafileOndisk (line 45) | typedef struct SeafileOndisk {
type DirentOndisk (line 51) | typedef struct DirentOndisk {
type SeafdirOndisk (line 58) | typedef struct SeafdirOndisk {
function SeafFSManager (line 73) | SeafFSManager *
function seaf_fs_manager_init (line 92) | int
function checkout_block (line 104) | static int
function seaf_fs_manager_checkout_file (line 213) | int
function seaf_fs_manager_calculate_seafile_id_json (line 398) | void
function write_seafile (line 434) | static int
function calculate_chunk_size (line 492) | uint32_t
function do_write_chunk (line 505) | static int
function seafile_write_chunk (line 555) | int
function create_cdc_for_empty_file (line 602) | static void
type ChunkingData (line 612) | typedef struct ChunkingData {
function chunking_worker (line 621) | static void
function split_file_to_block (line 672) | static int
function seaf_fs_manager_index_blocks (line 772) | int
function check_and_write_block (line 849) | static int
function check_and_write_file_blocks (line 889) | static int
function check_existed_file_blocks (line 920) | static int
function init_file_cdc (line 952) | static int
function seaf_fs_manager_index_file_blocks (line 973) | int
function seaf_fs_manager_index_raw_blocks (line 1017) | int
function seaf_fs_manager_index_existed_file_blocks (line 1045) | int
function seafile_ref (line 1087) | void
function seafile_free (line 1093) | static void
function seafile_unref (line 1107) | void
function Seafile (line 1117) | static Seafile *
function Seafile (line 1163) | static Seafile *
function Seafile (line 1222) | static Seafile *
function Seafile (line 1252) | static Seafile *
function Seafile (line 1261) | Seafile *
function guint8 (line 1306) | static guint8 *
function guint8 (line 1327) | static guint8 *
function guint8 (line 1357) | static guint8 *
function seafile_save (line 1380) | int
function compute_dir_id_v0 (line 1405) | static void compute_dir_id_v0 (SeafDir *dir, GList *entries)
function SeafDir (line 1436) | SeafDir *
function seaf_dir_free (line 1460) | void
function SeafDirent (line 1477) | SeafDirent *
function seaf_dirent_free (line 1508) | void
function SeafDirent (line 1518) | SeafDirent *
function SeafDir (line 1530) | static SeafDir *
function SeafDirent (line 1591) | static SeafDirent *
function SeafDir (line 1644) | static SeafDir *
function SeafDir (line 1697) | static SeafDir *
function SeafDir (line 1727) | SeafDir *
function ondisk_dirent_size (line 1737) | inline static int
function add_to_dirent_array (line 1779) | static void
function seaf_dir_save (line 1852) | int
function SeafDir (line 1874) | SeafDir *
function gint (line 1905) | static gint
function gboolean (line 1913) | static gboolean
function SeafDir (line 1936) | SeafDir *
function SeafDir (line 1957) | SeafDir *
function parse_metadata_type_v0 (line 1981) | static int
function parse_metadata_type_json (line 1992) | static int
function seaf_metadata_type_from_data (line 2022) | int
function SeafFSObject (line 2032) | SeafFSObject *
function SeafFSObject (line 2047) | SeafFSObject *
function SeafFSObject (line 2089) | SeafFSObject *
function seaf_fs_object_free (line 2100) | void
function BlockList (line 2112) | BlockList *
function block_list_free (line 2123) | void
function block_list_insert (line 2132) | void
function BlockList (line 2144) | BlockList *
function traverse_file (line 2167) | static int
function traverse_dir (line 2188) | static int
function seaf_fs_manager_traverse_tree (line 2243) | int
function traverse_dir_path (line 2258) | static int
function seaf_fs_manager_traverse_path (line 2311) | int
function gboolean (line 2337) | static gboolean
function seaf_fs_manager_populate_blocklist (line 2363) | int
function gboolean (line 2375) | gboolean
function seaf_fs_manager_delete_object (line 2388) | void
function gint64 (line 2397) | gint64
function gint64 (line 2418) | static gint64
function gint64 (line 2462) | gint64
function count_dir_files (line 2473) | static int
function get_file_count_info (line 2505) | static int
function seaf_fs_manager_count_fs_files (line 2541) | int
function SeafDir (line 2552) | SeafDir *
function SeafDirent (line 2746) | SeafDirent *
function gboolean (line 2793) | static gboolean
function gboolean (line 2868) | static gboolean
function gboolean (line 2888) | static gboolean
function gboolean (line 2898) | gboolean
function gboolean (line 2926) | static gboolean
function gboolean (line 2965) | static gboolean
function gboolean (line 2975) | gboolean
function gboolean (line 3003) | static gboolean
function gboolean (line 3027) | gboolean
function dir_version_from_repo_version (line 3059) | int
function seafile_version_from_repo_version (line 3068) | int
function seaf_fs_manager_remove_store (line 3077) | int
function GObject (line 3084) | GObject *
function search_files_recursive (line 3123) | static int
function GList (line 3176) | GList *
FILE: common/fs-mgr.h
type SeafFSManager (line 18) | typedef struct _SeafFSManager SeafFSManager;
type SeafFSObject (line 19) | typedef struct _SeafFSObject SeafFSObject;
type Seafile (line 20) | typedef struct _Seafile Seafile;
type SeafDir (line 21) | typedef struct _SeafDir SeafDir;
type SeafDirent (line 22) | typedef struct _SeafDirent SeafDirent;
type SeafMetadataType (line 24) | typedef enum {
type _SeafFSObject (line 32) | struct _SeafFSObject {
type _Seafile (line 36) | struct _Seafile {
type SearchResult (line 46) | typedef struct SearchResult {
type _SeafDirent (line 67) | struct _SeafDirent {
type _SeafDir (line 80) | struct _SeafDir {
type BlockList (line 133) | typedef struct {
type _SeafileSession (line 156) | struct _SeafileSession
type SeafFSManagerPriv (line 158) | typedef struct _SeafFSManagerPriv SeafFSManagerPriv;
type _SeafFSManager (line 160) | struct _SeafFSManager {
type _SeafileSession (line 169) | struct _SeafileSession
type SeafileCrypt (line 185) | struct SeafileCrypt
type gboolean (line 270) | typedef gboolean (*TraverseFSTreeCallback) (SeafFSManager *mgr,
type gboolean (line 287) | typedef gboolean (*TraverseFSPathCallback) (SeafFSManager *mgr,
type _CDCFileDescriptor (line 421) | struct _CDCFileDescriptor
type _CDCFileDescriptor (line 424) | struct _CDCFileDescriptor
FILE: common/group-mgr.c
type _CcnetGroupManagerPriv (line 16) | struct _CcnetGroupManagerPriv {
function CcnetGroupManager (line 24) | CcnetGroupManager* ccnet_group_manager_new (SeafileSession *session)
function ccnet_group_manager_init (line 34) | int
function ccnet_group_manager_prepare (line 40) | int
function ccnet_group_manager_start (line 52) | void ccnet_group_manager_start (CcnetGroupManager *manager)
function CcnetDB (line 56) | static CcnetDB *
function open_db (line 81) | static int
function check_db_table (line 111) | static int check_db_table (CcnetGroupManager *manager, CcnetDB *db)
function gboolean (line 235) | static gboolean
function gboolean (line 245) | static gboolean
function create_group_common (line 255) | static int
function ccnet_group_manager_create_group (line 346) | int ccnet_group_manager_create_group (CcnetGroupManager *mgr,
function ccnet_group_manager_create_org_group (line 387) | int ccnet_group_manager_create_org_group (CcnetGroupManager *mgr,
function gboolean (line 417) | static gboolean
function ccnet_group_manager_remove_group (line 462) | int ccnet_group_manager_remove_group (CcnetGroupManager *mgr,
function gboolean (line 510) | static gboolean
function ccnet_group_manager_add_member (line 533) | int ccnet_group_manager_add_member (CcnetGroupManager *mgr,
function ccnet_group_manager_remove_member (line 560) | int ccnet_group_manager_remove_member (CcnetGroupManager *mgr,
function ccnet_group_manager_set_admin (line 587) | int ccnet_group_manager_set_admin (CcnetGroupManager *mgr,
function ccnet_group_manager_unset_admin (line 602) | int ccnet_group_manager_unset_admin (CcnetGroupManager *mgr,
function ccnet_group_manager_set_group_name (line 617) | int ccnet_group_manager_set_group_name (CcnetGroupManager *mgr,
function ccnet_group_manager_quit_group (line 640) | int ccnet_group_manager_quit_group (CcnetGroupManager *mgr,
function gboolean (line 661) | static gboolean
function GList (line 687) | GList *
function gint (line 730) | static gint
function gboolean (line 744) | gboolean
function GList (line 758) | GList *
function gboolean (line 853) | static gboolean
function GList (line 883) | GList *
function GList (line 911) | GList *
function CcnetGroup (line 947) | CcnetGroup *
function gboolean (line 975) | static gboolean
function GList (line 999) | GList *
function GList (line 1032) | GList *
function ccnet_group_manager_check_group_staff (line 1073) | int
function ccnet_group_manager_remove_group_user (line 1082) | int
function ccnet_group_manager_is_group_user (line 1096) | int
function gboolean (line 1135) | static gboolean
function GList (line 1167) | GList *
function GList (line 1210) | GList*
function GList (line 1245) | GList*
function ccnet_group_manager_set_group_creator (line 1296) | int
function GList (line 1320) | GList *
function gboolean (line 1388) | static gboolean
function GList (line 1405) | GList *
function GList (line 1449) | GList*
function ccnet_group_manager_update_group_user (line 1476) | int
FILE: common/group-mgr.h
type SeafileSession (line 8) | typedef struct _SeafileSession SeafileSession;
type CcnetGroupManager (line 9) | typedef struct _CcnetGroupManager CcnetGroupManager;
type CcnetGroupManagerPriv (line 10) | typedef struct _CcnetGroupManagerPriv CcnetGroupManagerPriv;
type _CcnetGroupManager (line 12) | struct _CcnetGroupManager
FILE: common/log.c
function get_syslog_level (line 33) | static int
function seafile_log (line 54) | static void
function ccnet_log (line 98) | static void
function get_debug_level (line 136) | static int
function seafile_log_init (line 148) | int
function seafile_log_reopen (line 182) | int
function gboolean (line 218) | gboolean
function seafile_debug_set_flags (line 224) | void
function seafile_debug_set_flags_string (line 231) | void
function seafile_debug_impl (line 241) | void
function set_syslog_config (line 254) | void
FILE: common/log.h
type SeafileDebugFlags (line 33) | typedef enum
FILE: common/merge-new.c
function twoway_merge (line 118) | int twoway_merge(const char *store_id, int version, const char *basedir,
function threeway_merge (line 174) | static int
function merge_entries (line 408) | static int
function merge_directories (line 427) | static int
function gint (line 589) | static gint
function merge_trees_recursive (line 597) | static int
function seaf_merge_trees (line 715) | int
FILE: common/merge-new.h
type MergeOptions (line 8) | struct MergeOptions
type MergeOptions (line 12) | struct MergeOptions
type MergeOptions (line 14) | typedef struct MergeOptions {
FILE: common/mq-mgr.c
type SeafMqManagerPriv (line 6) | typedef struct SeafMqManagerPriv {
function SeafMqManager (line 11) | SeafMqManager *
function GAsyncQueue (line 23) | static GAsyncQueue *
function seaf_mq_manager_publish_event (line 34) | int
function json_t (line 62) | json_t *
FILE: common/mq-mgr.h
type SeafMqManagerPriv (line 9) | struct SeafMqManagerPriv
type SeafMqManager (line 11) | typedef struct SeafMqManager {
FILE: common/obj-backend-fs.c
type FsPriv (line 23) | typedef struct FsPriv {
function id_to_path (line 28) | static void
function obj_backend_fs_read (line 52) | static int
function fsync_obj_contents (line 95) | static int
function rename_and_sync (line 147) | static int
function save_obj_contents (line 217) | static int
function create_parent_path (line 261) | static int
function obj_backend_fs_write (line 284) | static int
function gboolean (line 321) | static gboolean
function obj_backend_fs_delete (line 338) | static void
function obj_backend_fs_foreach_obj (line 350) | static int
function obj_backend_fs_copy (line 409) | static int
function obj_backend_fs_remove_store (line 450) | static int
function ObjBackend (line 497) | ObjBackend *
FILE: common/obj-backend-riak.c
type RiakPriv (line 11) | typedef struct RiakPriv {
function SeafRiakClient (line 21) | static SeafRiakClient *
function return_connection (line 35) | static void
function obj_backend_riak_read (line 43) | static int
function obj_backend_riak_write (line 59) | static int
function gboolean (line 76) | static gboolean
function obj_backend_riak_delete (line 90) | static void
function ObjBackend (line 102) | ObjBackend *
function ObjBackend (line 138) | ObjBackend *
FILE: common/obj-backend.h
type ObjBackend (line 7) | typedef struct ObjBackend ObjBackend;
type ObjBackend (line 9) | struct ObjBackend {
FILE: common/obj-cache.c
type CacheOption (line 13) | typedef struct CacheOption {
function cache_option_free (line 22) | static void
function load_cache_option_from_env (line 33) | static void
function ObjCache (line 72) | ObjCache *
function objcache_set_object (line 109) | int
function gboolean (line 119) | gboolean
function objcache_delete_object (line 125) | int
function objcache_set_object_existence (line 131) | int
function objcache_get_object_existence (line 148) | int
function objcache_delete_object_existence (line 169) | int
function objcache_publish (line 183) | int
function objcache_push (line 191) | int
FILE: common/obj-cache.h
type ObjCache (line 10) | typedef struct ObjCache ObjCache;
type ObjCache (line 12) | struct ObjCache {
type ObjCache (line 49) | struct ObjCache
type ObjCache (line 52) | struct ObjCache
type ObjCache (line 59) | struct ObjCache
type ObjCache (line 62) | struct ObjCache
type ObjCache (line 65) | struct ObjCache
type ObjCache (line 68) | struct ObjCache
type ObjCache (line 71) | struct ObjCache
FILE: common/obj-store.c
type SeafObjStore (line 12) | struct SeafObjStore {
type SeafObjStore (line 15) | typedef struct SeafObjStore SeafObjStore;
type SeafObjStore (line 20) | struct SeafObjStore
function seaf_obj_store_init (line 38) | int
function seaf_obj_store_read_obj (line 44) | int
function seaf_obj_store_write_obj (line 61) | int
function gboolean (line 79) | gboolean
function seaf_obj_store_delete_obj (line 94) | void
function seaf_obj_store_foreach_obj (line 109) | int
function seaf_obj_store_copy_obj (line 121) | int
function seaf_obj_store_remove_store (line 137) | int
FILE: common/obj-store.h
type _SeafileSession (line 7) | struct _SeafileSession
type SeafObjStore (line 8) | struct SeafObjStore
type SeafObjStore (line 10) | struct SeafObjStore
type _SeafileSession (line 11) | struct _SeafileSession
type SeafObjStore (line 14) | struct SeafObjStore
type SeafObjStore (line 19) | struct SeafObjStore
type SeafObjStore (line 27) | struct SeafObjStore
type SeafObjStore (line 36) | struct SeafObjStore
type SeafObjStore (line 42) | struct SeafObjStore
type gboolean (line 47) | typedef gboolean (*SeafObjFunc) (const char *repo_id,
type SeafObjStore (line 53) | struct SeafObjStore
type SeafObjStore (line 60) | struct SeafObjStore
type SeafObjStore (line 68) | struct SeafObjStore
FILE: common/object-list.c
function ObjectList (line 8) | ObjectList *
function object_list_free (line 19) | void
function object_list_serialize (line 28) | void
function gboolean (line 46) | gboolean
FILE: common/object-list.h
type ObjectList (line 8) | typedef struct {
function gboolean (line 30) | inline static gboolean
function object_list_length (line 36) | inline static int
FILE: common/org-mgr.c
type _CcnetOrgManagerPriv (line 15) | struct _CcnetOrgManagerPriv
function CcnetOrgManager (line 23) | CcnetOrgManager* ccnet_org_manager_new (SeafileSession *session)
function ccnet_org_manager_init (line 33) | int
function ccnet_org_manager_prepare (line 39) | int
function CcnetDB (line 45) | static CcnetDB *
function open_db (line 70) | static int
function ccnet_org_manager_start (line 98) | void ccnet_org_manager_start (CcnetOrgManager *manager)
function check_db_table (line 104) | static int check_db_table (CcnetDB *db)
function ccnet_org_manager_create_org (line 211) | int ccnet_org_manager_create_org (CcnetOrgManager *mgr,
function ccnet_org_manager_remove_org (line 252) | int
function gboolean (line 272) | static gboolean
function GList (line 302) | GList *
function ccnet_org_manager_count_orgs (line 327) | int
function gboolean (line 342) | static gboolean
function CcnetOrganization (line 368) | CcnetOrganization *
function CcnetOrganization (line 388) | CcnetOrganization *
function ccnet_org_manager_add_org_user (line 408) | int
function ccnet_org_manager_remove_org_user (line 422) | int
function gboolean (line 434) | static gboolean
function GList (line 469) | GList *
function gboolean (line 491) | static gboolean
function GList (line 501) | GList *
function ccnet_org_manager_add_org_group (line 534) | int
function ccnet_org_manager_remove_org_group (line 546) | int
function ccnet_org_manager_is_org_group (line 559) | int
function ccnet_org_manager_get_org_id_by_group (line 577) | int
function gboolean (line 589) | static gboolean
function GList (line 601) | GList *
function gboolean (line 634) | static gboolean
function GList (line 660) | GList *
function GList (line 681) | GList *
function GList (line 717) | GList *
function ccnet_org_manager_org_user_exists (line 741) | int
function ccnet_org_manager_is_org_staff (line 774) | int
function ccnet_org_manager_set_org_staff (line 788) | int
function ccnet_org_manager_unset_org_staff (line 801) | int
function ccnet_org_manager_set_org_name (line 814) | int
FILE: common/org-mgr.h
type SeafileSession (line 6) | typedef struct _SeafileSession SeafileSession;
type CcnetOrgManager (line 7) | typedef struct _CcnetOrgManager CcnetOrgManager;
type CcnetOrgManagerPriv (line 8) | typedef struct _CcnetOrgManagerPriv CcnetOrgManagerPriv;
type _CcnetOrgManager (line 10) | struct _CcnetOrgManager
FILE: common/password-hash.c
type Pbkdf2Params (line 14) | typedef struct Pbkdf2Params {
function Pbkdf2Params (line 18) | static Pbkdf2Params *
function pbkdf2_sha256_derive_key (line 38) | static int
type Argon2idParams (line 58) | typedef struct Argon2idParams{
function Argon2idParams (line 68) | static Argon2idParams *
function argon2id_derive_key (line 107) | static int
function parse_pwd_hash_params (line 125) | void
function pwd_hash_derive_key (line 147) | int
FILE: common/password-hash.h
type PwdHashParams (line 9) | typedef struct _PwdHashParams {
FILE: common/processors/objecttx-common.h
type ObjectPack (line 47) | typedef struct {
FILE: common/redis-cache.c
type _RedisConnectionPool (line 11) | struct _RedisConnectionPool {
type RedisConnectionPool (line 18) | typedef struct _RedisConnectionPool RedisConnectionPool;
type _RedisConnection (line 20) | struct _RedisConnection {
type RedisConnection (line 26) | typedef struct _RedisConnection RedisConnection;
type RedisPriv (line 28) | typedef struct RedisPriv {
function redis_auth (line 33) | static int
function RedisConnection (line 65) | static RedisConnection *
function redis_connection_free (line 92) | static void
function RedisConnectionPool (line 104) | static RedisConnectionPool *
function RedisConnection (line 116) | static RedisConnection *
function redis_connection_pool_return_connection (line 153) | static void
function redis_cache_set_object (line 217) | int
function gboolean (line 262) | gboolean
function redis_cache_delete_object (line 302) | int
function redis_cache_publish (line 341) | int
function redis_cache_push (line 379) | int
function ObjCache (line 417) | ObjCache *
FILE: common/rpc-service.c
function GObject (line 38) | static GObject*
function free_repo_obj (line 107) | static void
function GList (line 115) | static GList *
function GList (line 139) | GList *
function GList (line 166) | GList*
function GList (line 174) | GList *
function seafile_del_repo_from_trash (line 187) | int
function seafile_empty_repo_trash (line 206) | int
function seafile_empty_repo_trash_by_owner (line 212) | int
function seafile_restore_repo_from_trash (line 223) | int
function seafile_publish_event (line 242) | int
function json_t (line 257) | json_t *
function GList (line 268) | GList*
function gint64 (line 287) | gint64
function GObject (line 294) | GObject*
function SeafileCommit (line 322) | SeafileCommit *
function GObject (line 345) | GObject*
type CollectParam (line 371) | struct CollectParam {
function gboolean (line 382) | static gboolean
function GList (line 431) | GList*
function do_unsync_repo (line 513) | static
function cancel_clone_tasks_by_account (line 544) | static void
function seafile_unsync_repos_by_account (line 563) | int
function seafile_remove_repo_tokens_by_account (line 600) | int
function seafile_set_repo_token (line 637) | int
function seafile_destroy_repo (line 669) | int
function GObject (line 698) | GObject *
function GList (line 758) | GList *
function GList (line 827) | GList *
function filter_error (line 913) | static void
function seafile_edit_repo (line 991) | int
function seafile_change_repo_passwd (line 1001) | int
function set_pwd_hash_to_commit (line 1135) | static void
function seafile_upgrade_repo_pwd_hash_algorithm (line 1165) | int
function seafile_is_repo_owner (line 1310) | int
function seafile_set_repo_owner (line 1335) | int
function GList (line 1371) | GList *
function GList (line 1388) | GList *
function GList (line 1424) | GList *
function gint64 (line 1441) | gint64
function gint64 (line 1460) | gint64
function gint64 (line 1479) | gint64
function seafile_set_repo_history_limit (line 1503) | int
function seafile_get_repo_history_limit (line 1528) | int
function seafile_set_repo_valid_since (line 1545) | int
function seafile_repo_set_access_property (line 1555) | int
function GObject (line 1625) | GObject *
function seafile_cancel_zip_task (line 1655) | int
function seafile_add_share (line 1666) | int
function GList (line 1701) | GList *
function GList (line 1718) | GList *
function seafile_unshare_subdir_for_user (line 1814) | int
function seafile_update_share_subdir_perm_for_user (line 1862) | int
function GList (line 1919) | GList *
function seafile_remove_share (line 1939) | int
function seafile_group_share_repo (line 1958) | int
function seafile_group_unshare_repo (line 1989) | int
function seafile_unshare_subdir_for_group (line 2083) | int
function seafile_update_share_subdir_perm_for_group (line 2130) | int
function GList (line 2242) | GList *
function GList (line 2259) | GList *
function seafile_remove_repo_group (line 2300) | int
function seafile_set_inner_pub_repo (line 2316) | int
function seafile_unset_inner_pub_repo (line 2340) | int
function GList (line 2361) | GList *
function gint64 (line 2367) | gint64
function GList (line 2373) | GList *
function seafile_is_inner_pub_repo (line 2384) | int
function gint64 (line 2400) | gint64
function gint64 (line 2428) | gint64
function seafile_check_passwd (line 2456) | int
function seafile_set_passwd (line 2476) | int
function seafile_unset_passwd (line 2497) | int
function seafile_is_passwd_set (line 2517) | int
function GObject (line 2530) | GObject *
function seafile_revert_on_server (line 2552) | int
function seafile_post_file (line 2583) | int
function seafile_post_dir (line 2850) | int
function seafile_post_empty_file (line 2900) | int
function seafile_del_file (line 2950) | int
function seafile_batch_del_files (line 3000) | int
function GObject (line 3040) | GObject *
function GObject (line 3116) | GObject *
function GObject (line 3193) | GObject *
function seafile_cancel_copy_task (line 3199) | int
function seafile_rename_file (line 3205) | int
function seafile_is_valid_filename (line 3267) | int
function seafile_set_user_quota (line 3343) | int
function gint64 (line 3355) | gint64
function seafile_check_quota (line 3367) | int
function GList (line 3383) | GList *
function GObject (line 3488) | GObject *
function gint (line 3618) | static gint
function GList (line 3632) | GList *
function GList (line 3707) | GList *
function GList (line 3736) | GList *
function seafile_revert_file (line 3763) | int
function seafile_revert_dir (line 3796) | int
function GList (line 3881) | GList *
function seafile_delete_repo_token (line 3932) | int
function GList (line 3952) | GList *
function GList (line 3973) | GList *
function seafile_delete_repo_tokens_by_peer_id (line 3989) | int
function seafile_delete_repo_tokens_by_email (line 4029) | int
function GList (line 4068) | GList *
function seafile_set_share_permission (line 4112) | int
function seafile_set_group_repo_permission (line 4143) | int
function GList (line 4259) | GList *
function GObject (line 4315) | GObject *
function update_valid_since_time (line 4349) | static int
function seafile_clean_up_repo_history (line 4379) | int
function GList (line 4414) | GList *
function GList (line 4440) | GList *
function gint64 (line 4466) | gint64
function gint64 (line 4472) | gint64
function GObject (line 4478) | GObject *
function seafile_mkdir_with_parents (line 4519) | int
function seafile_set_server_config_int (line 4543) | int
function seafile_get_server_config_int (line 4555) | int
function seafile_set_server_config_int64 (line 4566) | int
function gint64 (line 4578) | gint64
function seafile_set_server_config_string (line 4589) | int
function seafile_set_server_config_boolean (line 4612) | int
function seafile_get_server_config_boolean (line 4624) | int
function GObject (line 4635) | GObject *
function GObject (line 4651) | GObject *
function GList (line 4667) | GList *
function GList (line 4679) | GList *
function seafile_repo_has_been_shared (line 4691) | int
function GList (line 4704) | GList *
function GList (line 4716) | GList *
function gint64 (line 4732) | gint64
function seafile_set_repo_status (line 4776) | int
function seafile_get_repo_status (line 4788) | int
function GList (line 4803) | GList *
function GList (line 4809) | GList *
function ccnet_rpc_add_emailuser (line 4835) | int
function ccnet_rpc_remove_emailuser (line 4853) | int
function ccnet_rpc_validate_emailuser (line 4869) | int
function GObject (line 4888) | GObject*
function GObject (line 4904) | GObject*
function GObject (line 4920) | GObject*
function GList (line 4931) | GList*
function GList (line 4945) | GList*
function GList (line 4962) | GList*
function GList (line 4976) | GList *
function GList (line 4987) | GList*
function GList (line 4998) | GList*
function GList (line 5009) | GList*
function gint64 (line 5020) | gint64
function gint64 (line 5028) | gint64
function ccnet_rpc_update_emailuser (line 5036) | int
function ccnet_rpc_update_role_emailuser (line 5047) | int
function GList (line 5056) | GList*
function GList (line 5064) | GList *
function ccnet_rpc_update_emailuser_id (line 5076) | int
function ccnet_rpc_create_group (line 5088) | int
function ccnet_rpc_create_org_group (line 5106) | int
function ccnet_rpc_remove_group (line 5124) | int
function ccnet_rpc_group_add_member (line 5142) | int
function ccnet_rpc_group_remove_member (line 5161) | int
function ccnet_rpc_group_set_admin (line 5180) | int
function ccnet_rpc_group_unset_admin (line 5198) | int
function ccnet_rpc_set_group_name (line 5216) | int
function ccnet_rpc_quit_group (line 5234) | int
function GList (line 5251) | GList *
function GList (line 5268) | GList *
function GList (line 5279) | GList*
function GList (line 5304) | GList *
function GList (line 5316) | GList *
function GObject (line 5327) | GObject *
function GList (line 5343) | GList *
function GList (line 5360) | GList *
function ccnet_rpc_check_group_staff (line 5371) | int
function ccnet_rpc_remove_group_user (line 5388) | int
function ccnet_rpc_is_group_user (line 5400) | int
function ccnet_rpc_set_group_creator (line 5412) | int
function GList (line 5426) | GList *
function ccnet_rpc_create_org (line 5438) | int
function ccnet_rpc_remove_org (line 5453) | int
function GList (line 5489) | GList *
function gint64 (line 5500) | gint64
function GObject (line 5509) | GObject *
function GObject (line 5527) | GObject *
function ccnet_rpc_add_org_user (line 5545) | int
function ccnet_rpc_remove_org_user (line 5560) | int
function GList (line 5573) | GList *
function GList (line 5584) | GList *
function ccnet_rpc_add_org_group (line 5621) | int
function ccnet_rpc_remove_org_group (line 5634) | int
function ccnet_rpc_is_org_group (line 5648) | int
function ccnet_rpc_get_org_id_by_group (line 5661) | int
function GList (line 5674) | GList *
function GList (line 5695) | GList *
function GList (line 5710) | GList *
function ccnet_rpc_org_user_exists (line 5725) | int
function ccnet_rpc_is_org_staff (line 5738) | int
function ccnet_rpc_set_org_staff (line 5751) | int
function ccnet_rpc_unset_org_staff (line 5764) | int
function ccnet_rpc_set_org_name (line 5777) | int
FILE: common/seaf-db.c
type DBConnPool (line 16) | struct DBConnPool {
type DBConnPool (line 21) | typedef struct DBConnPool DBConnPool;
type SeafDB (line 23) | struct SeafDB {
type DBConnection (line 28) | typedef struct DBConnection {
type SeafDBRow (line 34) | struct SeafDBRow {
type SeafDBTrans (line 38) | struct SeafDBTrans {
type DBOperations (line 43) | typedef struct DBOperations {
function DBConnPool (line 97) | static DBConnPool *
function DBConnection (line 108) | static DBConnection *
function mysql_conn_pool_release_connection (line 162) | static void
function SeafDB (line 231) | SeafDB *
function SeafDB (line 300) | SeafDB *
function seaf_db_type (line 323) | int
function seaf_db_query (line 329) | int
function gboolean (line 355) | gboolean
function seaf_db_foreach_selected_row (line 361) | int
function seaf_db_row_get_column_int (line 376) | int
function gint64 (line 384) | gint64
function seaf_db_get_int (line 392) | int
function gint64 (line 398) | gint64
function seaf_db_statement_query (line 410) | int
function gboolean (line 439) | gboolean
function seaf_db_statement_foreach_row (line 476) | int
function gboolean (line 507) | static gboolean
function seaf_db_statement_get_int (line 517) | int
function gboolean (line 547) | static gboolean
function gint64 (line 557) | gint64
function gboolean (line 587) | static gboolean
function SeafDBTrans (line 629) | SeafDBTrans *
function seaf_db_trans_close (line 649) | void
function seaf_db_commit (line 656) | int
function seaf_db_rollback (line 669) | int
function seaf_db_trans_query (line 682) | int
function gboolean (line 698) | gboolean
function seaf_db_trans_foreach_selected_row (line 721) | int
function seaf_db_row_get_column_count (line 739) | int
type MySQLDB (line 749) | typedef struct MySQLDB {
type MySQLDBConnection (line 763) | typedef struct MySQLDBConnection {
function gboolean (line 768) | static gboolean
function SeafDB (line 776) | static SeafDB *
type my_bool (line 806) | typedef char my_bool;
function DBConnection (line 808) | static DBConnection *
function mysql_db_release_connection (line 886) | static void
function mysql_db_execute_sql_no_stmt (line 899) | static int
function MYSQL_STMT (line 919) | static MYSQL_STMT *
function _bind_params_mysql (line 944) | static int
function mysql_db_execute_sql (line 995) | static int
type MySQLDBRow (line 1046) | typedef struct MySQLDBRow {
function mysql_db_query_foreach_row (line 1057) | static int
function mysql_db_row_get_column_count (line 1190) | static int
function mysql_db_row_get_column_int (line 1231) | static int
function gint64 (line 1253) | static gint64
type UnlockNotification (line 1283) | typedef struct UnlockNotification {
function unlock_notify_cb (line 1289) | static void
function wait_for_unlock_notify (line 1303) | static int
function sqlite3_blocking_step (line 1326) | static int
function sqlite3_blocking_prepare_v2 (line 1339) | static int
function sqlite3_blocking_exec (line 1351) | static int
type SQLiteDB (line 1363) | typedef struct SQLiteDB {
type SQLiteDBConnection (line 1368) | typedef struct SQLiteDBConnection {
function SeafDB (line 1373) | static SeafDB *
function DBConnection (line 1382) | static DBConnection *
function sqlite_db_release_connection (line 1404) | static void
function sqlite_db_execute_sql_no_stmt (line 1417) | static int
function _bind_parameters_sqlite (line 1435) | static int
function sqlite_db_execute_sql (line 1470) | static int
type SQLiteDBRow (line 1503) | typedef struct SQLiteDBRow {
function sqlite_db_query_foreach_row (line 1510) | static int
function sqlite_db_row_get_column_count (line 1559) | static int
function sqlite_db_row_get_column_int (line 1575) | static int
function gint64 (line 1583) | static gint64
FILE: common/seaf-db.h
type SeafDB (line 10) | typedef struct SeafDB SeafDB;
type CcnetDB (line 11) | typedef struct SeafDB CcnetDB;
type SeafDBRow (line 12) | typedef struct SeafDBRow SeafDBRow;
type CcnetDBRow (line 13) | typedef struct SeafDBRow CcnetDBRow;
type SeafDBTrans (line 14) | typedef struct SeafDBTrans SeafDBTrans;
type CcnetDBTrans (line 15) | typedef struct SeafDBTrans CcnetDBTrans;
type gboolean (line 17) | typedef gboolean (*SeafDBRowFunc) (SeafDBRow *, void *);
type gboolean (line 18) | typedef gboolean (*CcnetDBRowFunc) (CcnetDBRow *, void *);
FILE: common/seaf-utils.c
function sqlite_db_start (line 37) | static int
type DBOption (line 63) | typedef struct DBOption {
function db_option_free (line 77) | static void
function load_db_option_from_env (line 92) | static int
function DBOption (line 140) | static DBOption *
function mysql_db_start (line 229) | static int
function pgsql_db_start (line 256) | static int
function load_database_config (line 314) | int
function ccnet_init_sqlite_database (line 344) | static int
function ccnet_init_mysql_database (line 360) | static int
function load_ccnet_database_config (line 385) | int
function split_filename (line 489) | void
function gboolean (line 504) | static gboolean
function seaf_delete_repo_tokens (line 516) | int
FILE: common/seaf-utils.h
type _SeafileSession (line 6) | struct _SeafileSession
type _SeafileSession (line 9) | struct _SeafileSession
type _SeafileSession (line 14) | struct _SeafileSession
type _SeafileSession (line 17) | struct _SeafileSession
FILE: common/seafile-crypt.c
function SeafileCrypt (line 26) | SeafileCrypt *
function seafile_derive_key (line 39) | int
function seafile_generate_repo_salt (line 91) | int
function seafile_generate_random_key (line 107) | int
function seafile_generate_magic (line 139) | void
function seafile_generate_pwd_hash (line 160) | void
function seafile_verify_repo_passwd (line 191) | int
function seafile_pwd_hash_verify_repo_passwd (line 224) | int
function seafile_decrypt_repo_enc_key (line 257) | int
function seafile_update_random_key (line 306) | int
function seafile_encrypt (line 350) | int
function seafile_decrypt (line 459) | int
function seafile_decrypt_init (line 558) | int
FILE: common/seafile-crypt.h
type SeafileCrypt (line 22) | struct SeafileCrypt {
type SeafileCrypt (line 28) | typedef struct SeafileCrypt SeafileCrypt;
FILE: common/user-mgr.c
type CcnetUserManagerPriv (line 36) | struct CcnetUserManagerPriv {
function ccnet_user_manager_class_init (line 41) | static void
function ccnet_user_manager_init (line 48) | static void
function CcnetUserManager (line 54) | CcnetUserManager*
function get_current_user_number (line 69) | static int
function gboolean (line 84) | static gboolean
function ccnet_user_manager_prepare (line 106) | int
function ccnet_user_manager_free (line 126) | void
function ccnet_user_manager_start (line 132) | void
function ccnet_user_manager_on_exit (line 138) | void ccnet_user_manager_on_exit (CcnetUserManager *manager)
function ccnet_user_manager_set_max_users (line 142) | void
function check_db_table (line 150) | static int check_db_table (SeafDB *db)
function CcnetDB (line 272) | static CcnetDB *
function open_db (line 295) | static int
function hash_password (line 334) | static void
function hash_password_salted (line 346) | static void
function hash_password_pbkdf2_sha256 (line 359) | static void
function gboolean (line 392) | static gboolean
function gboolean (line 432) | static gboolean
function update_user_passwd (line 457) | static int
function ccnet_user_manager_add_emailuser (line 484) | int
function ccnet_user_manager_remove_emailuser (line 527) | int
function gboolean (line 549) | static gboolean
function ccnet_user_manager_validate_emailuser (line 558) | int
function gboolean (line 619) | static gboolean
function CcnetEmailUser (line 654) | static CcnetEmailUser*
function CcnetEmailUser (line 700) | CcnetEmailUser*
function CcnetEmailUser (line 708) | CcnetEmailUser*
function CcnetEmailUser (line 716) | CcnetEmailUser*
function gboolean (line 733) | static gboolean
function GList (line 765) | GList*
function GList (line 832) | GList*
function gint64 (line 885) | gint64
function gint64 (line 903) | gint64
function GList (line 922) | GList*
function ccnet_user_manager_update_emailuser (line 957) | int
function gboolean (line 993) | static gboolean
function ccnet_user_manager_update_role_emailuser (line 1018) | int
function GList (line 1035) | GList*
function GList (line 1067) | GList *
function ccnet_user_manager_update_emailuser_id (line 1128) | int
FILE: common/user-mgr.h
type SeafileSession (line 17) | typedef struct _SeafileSession SeafileSession;
type CcnetUserManager (line 18) | typedef struct _CcnetUserManager CcnetUserManager;
type CcnetUserManagerClass (line 19) | typedef struct _CcnetUserManagerClass CcnetUserManagerClass;
type CcnetUserManagerPriv (line 21) | typedef struct CcnetUserManagerPriv CcnetUserManagerPriv;
type _CcnetUserManager (line 24) | struct _CcnetUserManager
type _CcnetUserManagerClass (line 53) | struct _CcnetUserManagerClass
FILE: common/vc-common.c
function gint (line 12) | static gint
function gint (line 22) | static gint
function gboolean (line 31) | static gboolean
function GHashTable (line 42) | static GHashTable *
function GList (line 66) | static GList *
type MergeTraverseData (line 118) | typedef struct {
function gboolean (line 123) | static gboolean
function GList (line 149) | static GList *
function SeafCommit (line 212) | SeafCommit *
function gboolean (line 259) | gboolean
function VCCompareResult (line 270) | VCCompareResult
function diff_parents_with_path (line 317) | static int
function get_file_modifier_mtime_v0 (line 423) | static int
function get_file_modifier_mtime_v1 (line 499) | static int
function get_file_modifier_mtime (line 564) | int
FILE: common/vc-common.h
type VCCompareResult (line 16) | typedef enum {
FILE: controller/seafile-controller.c
type option (line 41) | struct option
function controller_exit (line 60) | static void
function spawn_process (line 74) | static int
function read_pid_from_pidfile (line 141) | static int
function kill_by_force (line 165) | static void
function start_seaf_server (line 185) | static int
function start_go_fileserver (line 215) | static int
function init_seafile_path (line 275) | static void
function setup_python_path (line 297) | static void
function setup_env (line 344) | static void
function start_seafdav (line 360) | static int
function run_controller_loop (line 410) | static void
function gboolean (line 418) | static gboolean
function gboolean (line 443) | static gboolean
function gboolean (line 488) | static gboolean
function start_process_monitor (line 513) | static void
function stop_services (line 522) | static void
function init_pidfile_path (line 532) | static void
function seaf_controller_init (line 548) | static int
function seaf_controller_start (line 593) | static int
function write_controller_pidfile (line 612) | static int
function remove_controller_pidfile (line 641) | static void
function sigint_handler (line 649) | static void
function sigchld_handler (line 660) | static void
function sigusr1_handler (line 666) | static void
function set_signal_handlers (line 672) | static void
function usage (line 682) | static void
function test_config (line 694) | static void
function read_seafdav_config (line 740) | static int
function init_syslog_config (line 819) | static int
function main (line 843) | int main (int argc, char **argv)
FILE: controller/seafile-controller.h
type SeafileController (line 23) | typedef struct _SeafileController SeafileController;
type SeafDavConfig (line 34) | typedef struct SeafDavConfig {
type _SeafileController (line 42) | struct _SeafileController {
FILE: fileserver/blockmgr/blockmgr.go
function Init (line 12) | func Init(seafileConfPath string, seafileDataDir string) {
function Read (line 17) | func Read(repoID string, blockID string, w io.Writer) error {
function Write (line 27) | func Write(repoID string, blockID string, r io.Reader) error {
function Exists (line 37) | func Exists(repoID string, blockID string) bool {
function Stat (line 43) | func Stat(repoID string, blockID string) (int64, error) {
FILE: fileserver/blockmgr/blockmgr_test.go
constant blockID (line 12) | blockID = "0401fc662e3bc87a41f299a907c056aaf8322a27"
constant repoID (line 13) | repoID = "b1f2ad61-9164-418a-a47f-ab805dbd5694"
constant seafileConfPath (line 14) | seafileConfPath = "/tmp/conf"
constant seafileDataDir (line 15) | seafileDataDir = "/tmp/conf/seafile-data"
constant testFile (line 16) | testFile = "output.data"
function delFile (line 19) | func delFile() error {
function createFile (line 33) | func createFile() error {
function TestMain (line 48) | func TestMain(m *testing.M) {
function testBlockRead (line 63) | func testBlockRead(t *testing.T) {
function testBlockWrite (line 71) | func testBlockWrite(t *testing.T) {
function testBlockExists (line 84) | func testBlockExists(t *testing.T) {
function TestBlock (line 98) | func TestBlock(t *testing.T) {
FILE: fileserver/commitmgr/commitmgr.go
type Commit (line 19) | type Commit struct
method FromData (line 89) | func (commit *Commit) FromData(p []byte) error {
method ToData (line 115) | func (commit *Commit) ToData(w io.Writer) error {
function Init (line 51) | func Init(seafileConfPath string, seafileDataDir string) {
function NewCommit (line 56) | func NewCommit(repoID, parentID, newRoot, user, desc string) *Commit {
function computeCommitID (line 72) | func computeCommitID(commit *Commit) string {
function ReadRaw (line 130) | func ReadRaw(repoID string, commitID string, w io.Writer) error {
function WriteRaw (line 139) | func WriteRaw(repoID string, commitID string, r io.Reader) error {
function Load (line 148) | func Load(repoID string, commitID string) (*Commit, error) {
function Save (line 164) | func Save(commit *Commit) error {
function Exists (line 180) | func Exists(repoID string, commitID string) (bool, error) {
FILE: fileserver/commitmgr/commitmgr_test.go
constant commitID (line 11) | commitID = "0401fc662e3bc87a41f299a907c056aaf8322a27"
constant rootID (line 12) | rootID = "6a1608dc2a1248838464e9b194800d35252e2ce3"
constant repoID (line 13) | repoID = "b1f2ad61-9164-418a-a47f-ab805dbd5694"
constant seafileConfPath (line 14) | seafileConfPath = "/tmp/conf"
constant seafileDataDir (line 15) | seafileDataDir = "/tmp/conf/seafile-data"
function delFile (line 18) | func delFile() error {
function TestMain (line 27) | func TestMain(m *testing.M) {
function assertEqual (line 37) | func assertEqual(t *testing.T, a, b interface{}) {
function TestCommit (line 43) | func TestCommit(t *testing.T) {
FILE: fileserver/commitmgr/null.go
type String (line 15) | type String struct
method ValueOrZero (line 33) | func (s String) ValueOrZero() string {
method UnmarshalJSON (line 52) | func (s *String) UnmarshalJSON(data []byte) error {
method MarshalJSON (line 68) | func (s String) MarshalJSON() ([]byte, error) {
method MarshalText (line 77) | func (s String) MarshalText() ([]byte, error) {
method UnmarshalText (line 86) | func (s *String) UnmarshalText(text []byte) error {
method SetValid (line 93) | func (s *String) SetValid(v string) {
method Ptr (line 99) | func (s String) Ptr() *string {
method IsZero (line 107) | func (s String) IsZero() bool {
method Equal (line 112) | func (s String) Equal(other String) bool {
function StringFrom (line 20) | func StringFrom(s string) String {
function StringFromPtr (line 25) | func StringFromPtr(s *string) String {
function NewString (line 41) | func NewString(s string, valid bool) String {
FILE: fileserver/crypt.go
type seafileCrypt (line 9) | type seafileCrypt struct
method encrypt (line 15) | func (crypt *seafileCrypt) encrypt(input []byte) ([]byte, error) {
method decrypt (line 41) | func (crypt *seafileCrypt) decrypt(input []byte) ([]byte, error) {
function pkcs7Padding (line 70) | func pkcs7Padding(p []byte, blockSize int) []byte {
function pkcs7UnPadding (line 76) | func pkcs7UnPadding(p []byte) []byte {
function to16Bytes (line 82) | func to16Bytes(input []byte) []byte {
FILE: fileserver/diff/diff.go
constant EmptySha1 (line 17) | EmptySha1 = "0000000000000000000000000000000000000000"
type fileCB (line 20) | type fileCB
type dirCB (line 21) | type dirCB
type DiffOptions (line 23) | type DiffOptions struct
type diffData (line 32) | type diffData struct
function DiffTrees (line 37) | func DiffTrees(roots []string, opt *DiffOptions) error {
function diffTreesRecursive (line 60) | func diffTreesRecursive(trees []*fsmgr.SeafDir, baseDir string, opt *Dif...
function diffFiles (line 127) | func diffFiles(baseDir string, dents []*fsmgr.SeafDirent, opt *DiffOptio...
function diffDirectories (line 145) | func diffDirectories(baseDir string, dents []*fsmgr.SeafDirent, opt *Dif...
function direntSame (line 188) | func direntSame(dentA, dentB *fsmgr.SeafDirent) bool {
constant DiffTypeCommits (line 196) | DiffTypeCommits = 'C'
constant DiffStatusAdded (line 198) | DiffStatusAdded = 'A'
constant DiffStatusDeleted (line 199) | DiffStatusDeleted = 'D'
constant DiffStatusModified (line 200) | DiffStatusModified = 'M'
constant DiffStatusRenamed (line 201) | DiffStatusRenamed = 'R'
constant DiffStatusUnmerged (line 202) | DiffStatusUnmerged = 'U'
constant DiffStatusDirAdded (line 203) | DiffStatusDirAdded = 'B'
constant DiffStatusDirDeleted (line 204) | DiffStatusDirDeleted = 'C'
constant DiffStatusDirRenamed (line 205) | DiffStatusDirRenamed = 'E'
type DiffEntry (line 208) | type DiffEntry struct
function diffEntryNewFromDirent (line 218) | func diffEntryNewFromDirent(diffType, status rune, dent *fsmgr.SeafDiren...
function diffEntryNew (line 229) | func diffEntryNew(diffType, status rune, dirID, name string) *DiffEntry {
function DiffMergeRoots (line 239) | func DiffMergeRoots(storeID, mergedRoot, p1Root, p2Root string, results ...
function threewayDiffFiles (line 259) | func threewayDiffFiles(ctx context.Context, baseDir string, dents []*fsm...
function threewayDiffDirs (line 296) | func threewayDiffDirs(ctx context.Context, baseDir string, dents []*fsmg...
function DiffCommitRoots (line 301) | func DiffCommitRoots(storeID, p1Root, p2Root string, results *[]*DiffEnt...
function DiffCommits (line 321) | func DiffCommits(commit1, commit2 *commitmgr.Commit, results *[]*DiffEnt...
function twowayDiffFiles (line 346) | func twowayDiffFiles(ctx context.Context, baseDir string, dents []*fsmgr...
function twowayDiffDirs (line 377) | func twowayDiffDirs(ctx context.Context, baseDir string, dents []*fsmgr....
function diffResolveRenames (line 412) | func diffResolveRenames(des *[]*DiffEntry) error {
function DiffResultsToDesc (line 535) | func DiffResultsToDesc(results []*DiffEntry) string {
FILE: fileserver/diff/diff_test.go
constant emptySHA1 (line 14) | emptySHA1 = "0000000000000000000000000000000000000000"
constant diffTestSeafileConfPath (line 15) | diffTestSeafileConfPath = "/tmp/conf"
constant diffTestSeafileDataDir (line 16) | diffTestSeafileDataDir = "/tmp/conf/seafile-data"
constant diffTestRepoID (line 17) | diffTestRepoID = "0d18a711-c988-4f7b-960c-211b34705ce3"
function TestDiffTrees (line 46) | func TestDiffTrees(t *testing.T) {
function diffTestCreateTestDir (line 67) | func diffTestCreateTestDir() error {
function testDiffTrees1 (line 117) | func testDiffTrees1(t *testing.T) {
function testDiffTrees2 (line 137) | func testDiffTrees2(t *testing.T) {
function testDiffTrees3 (line 158) | func testDiffTrees3(t *testing.T) {
function testDiffTrees4 (line 182) | func testDiffTrees4(t *testing.T) {
function testDiffTrees5 (line 206) | func testDiffTrees5(t *testing.T) {
function diffTestCreateSeafdir (line 226) | func diffTestCreateSeafdir(dents []*fsmgr.SeafDirent) (string, error) {
function diffTestDelFile (line 239) | func diffTestDelFile() error {
function diffTestFileCB (line 248) | func diffTestFileCB(ctx context.Context, baseDir string, files []*fsmgr....
function diffTestDirCB (line 265) | func diffTestDirCB(ctx context.Context, baseDir string, dirs []*fsmgr.Se...
FILE: fileserver/fileop.go
constant cacheBlockMapThreshold (line 46) | cacheBlockMapThreshold = 1 << 23
constant blockMapCacheExpiretime (line 47) | blockMapCacheExpiretime int64 = 3600 * 24
constant fileopCleaningIntervalSec (line 48) | fileopCleaningIntervalSec = 3600
constant duplicateNamesCount (line 49) | duplicateNamesCount = 1000
type Dirents (line 58) | type Dirents
method Less (line 60) | func (d Dirents) Less(i, j int) bool {
method Swap (line 64) | func (d Dirents) Swap(i, j int) {
method Len (line 67) | func (d Dirents) Len() int {
function fileopInit (line 71) | func fileopInit() {
function initUpload (line 82) | func initUpload() {
function parseContentType (line 88) | func parseContentType(fileName string) string {
function accessCB (line 154) | func accessCB(rsp http.ResponseWriter, r *http.Request) *appError {
function parseCryptKey (line 221) | func parseCryptKey(rsp http.ResponseWriter, repoID string, user string, ...
function accessV2CB (line 263) | func accessV2CB(rsp http.ResponseWriter, r *http.Request) *appError {
type UserInfo (line 345) | type UserInfo struct
function checkFileAccess (line 349) | func checkFileAccess(repoID, token, cookie, filePath, op, ipAddr, userAg...
function doFile (line 399) | func doFile(rsp http.ResponseWriter, r *http.Request, repo *repomgr.Repo...
function isNetworkErr (line 465) | func isNetworkErr(err error) bool {
type blockMap (line 470) | type blockMap struct
function doFileRange (line 475) | func doFileRange(rsp http.ResponseWriter, r *http.Request, repo *repomgr...
function parseRange (line 633) | func parseRange(byteRanges string, fileSize uint64) (uint64, uint64, boo...
function setCommonHeaders (line 683) | func setCommonHeaders(rsp http.ResponseWriter, r *http.Request, operatio...
function accessBlksCB (line 713) | func accessBlksCB(rsp http.ResponseWriter, r *http.Request) *appError {
function doBlock (line 762) | func doBlock(rsp http.ResponseWriter, r *http.Request, repo *repomgr.Rep...
function accessZipCB (line 817) | func accessZipCB(rsp http.ResponseWriter, r *http.Request) *appError {
function downloadZipFile (line 856) | func downloadZipFile(rsp http.ResponseWriter, r *http.Request, data, rep...
function genUniqueFileName (line 948) | func genUniqueFileName(fileName string, fileList []string) string {
function nameInFileList (line 972) | func nameInFileList(fileName string, fileList []string) bool {
function parseDirFilelist (line 981) | func parseDirFilelist(repo *repomgr.Repo, obj map[string]interface{}) ([...
function packDir (line 1040) | func packDir(ar *zip.Writer, repo *repomgr.Repo, dirID, dirPath string, ...
function packFiles (line 1078) | func packFiles(ar *zip.Writer, dirent *fsmgr.SeafDirent, repo *repomgr.R...
type recvData (line 1125) | type recvData struct
function uploadAPICB (line 1138) | func uploadAPICB(rsp http.ResponseWriter, r *http.Request) *appError {
function setAccessControl (line 1159) | func setAccessControl(rsp http.ResponseWriter) {
function uploadAjaxCB (line 1166) | func uploadAjaxCB(rsp http.ResponseWriter, r *http.Request) *appError {
function formatJSONError (line 1187) | func formatJSONError(rsp http.ResponseWriter, err *appError) {
function normalizeUTF8Path (line 1194) | func normalizeUTF8Path(p string) string {
function doUpload (line 1199) | func doUpload(rsp http.ResponseWriter, r *http.Request, fsm *recvData, i...
function writeBlockDataToTmpFile (line 1361) | func writeBlockDataToTmpFile(r *http.Request, fsm *recvData, formFiles m...
function getFileNameFromMimeHeader (line 1414) | func getFileNameFromMimeHeader(r *http.Request) (string, error) {
function createRelativePath (line 1435) | func createRelativePath(repoID, parentDir, relativePath, user string) *a...
function mkdirWithParents (line 1450) | func mkdirWithParents(repoID, parentDir, newDirPath, user string) error {
function checkAndCreateDir (line 1517) | func checkAndCreateDir(repo *repomgr.Repo, rootID, parentDir string, sub...
function genDirRecursive (line 1567) | func genDirRecursive(repo *repomgr.Repo, toPath []string) (string, error) {
function clearTmpFile (line 1613) | func clearTmpFile(fsm *recvData, parentDir string) {
function parseUploadHeaders (line 1624) | func parseUploadHeaders(r *http.Request) (*recvData, *appError) {
function checkQuotaByContentLength (line 1718) | func checkQuotaByContentLength(r *http.Request, repoID string, contentLe...
function checkFileSizeByContentLength (line 1737) | func checkFileSizeByContentLength(r *http.Request, contentLen int64) *ap...
function postMultiFiles (line 1750) | func postMultiFiles(rsp http.ResponseWriter, r *http.Request, repoID, pa...
function checkFilesWithSameName (line 1864) | func checkFilesWithSameName(repo *repomgr.Repo, canonPath string, fileNa...
function postFilesAndGenCommit (line 1884) | func postFilesAndGenCommit(fileNames []string, repoID string, user, cano...
function formatJSONRet (line 1965) | func formatJSONRet(nameList, idList []string, sizeList []int64) ([]byte,...
function getCanonPath (line 1987) | func getCanonPath(p string) string {
function genNewCommit (line 1997) | func genNewCommit(repo *repomgr.Repo, base *commitmgr.Commit, newRoot, u...
function fastForwardOrMerge (line 2042) | func fastForwardOrMerge(user, token string, repo *repomgr.Repo, base, ne...
function genCommitNeedRetry (line 2074) | func genCommitNeedRetry(repo *repomgr.Repo, base *commitmgr.Commit, comm...
function genMergeDesc (line 2141) | func genMergeDesc(repo *repomgr.Repo, mergedRoot, p1Root, p2Root string)...
function updateBranch (line 2153) | func updateBranch(repoID, originRepoID, newCommitID, oldCommitID, second...
function onBranchUpdated (line 2225) | func onBranchUpdated(repoID string, commitID string, updateRepoInfo bool...
type notifEvent (line 2247) | type notifEvent struct
type repoUpdateEvent (line 2251) | type repoUpdateEvent struct
function notifRepoUpdate (line 2256) | func notifRepoUpdate(repoID string, commitID string) error {
function doPostMultiFiles (line 2288) | func doPostMultiFiles(repo *repomgr.Repo, rootID, parentDir string, dent...
function postMultiFilesRecursive (line 2302) | func postMultiFilesRecursive(repo *repomgr.Repo, dirID, toPath, user str...
function addNewEntries (line 2378) | func addNewEntries(repo *repomgr.Repo, user string, oldDents *[]*fsmgr.S...
function genUniqueName (line 2412) | func genUniqueName(fileName string, entries []*fsmgr.SeafDirent) string {
function nameExists (line 2439) | func nameExists(entries []*fsmgr.SeafDirent, fileName string) bool {
function shouldIgnore (line 2449) | func shouldIgnore(fileName string) bool {
function shouldIgnoreFile (line 2459) | func shouldIgnoreFile(fileName string) bool {
function indexBlocks (line 2480) | func indexBlocks(ctx context.Context, repoID string, version int, filePa...
type indexFileRequest (line 2497) | type indexFileRequest struct
type indexFileResult (line 2506) | type indexFileResult struct
function indexFileWorker (line 2512) | func indexFileWorker(args ...any) error {
function writeSeafile (line 2614) | func writeSeafile(repoID string, version int, fileSize int64, blkIDs []s...
type chunkingData (line 2630) | type chunkingData struct
type chunkingResult (line 2638) | type chunkingResult struct
function createChunkPool (line 2644) | func createChunkPool(ctx context.Context, n int, chunkJobs chan chunking...
function chunkingWorker (line 2659) | func chunkingWorker(ctx context.Context, wg *sync.WaitGroup, chunkJobs c...
function chunkFile (line 2685) | func chunkFile(job chunkingData) (string, error) {
function writeChunk (line 2732) | func writeChunk(repoID string, input []byte, blkSize int64, cryptKey *se...
function checkTmpFileList (line 2768) | func checkTmpFileList(fsm *recvData) *appError {
function checkParentDir (line 2794) | func checkParentDir(repoID string, parentDir string) *appError {
function isParentMatched (line 2820) | func isParentMatched(uploadDir, parentDir string) bool {
function parseContentRange (line 2826) | func parseContentRange(ranges string, fsm *recvData) bool {
type webaccessInfo (line 2862) | type webaccessInfo struct
function parseWebaccessInfo (line 2869) | func parseWebaccessInfo(token string) (*webaccessInfo, *appError) {
function updateDir (line 2913) | func updateDir(repoID, dirPath, newDirID, user, headID string) (string, ...
function genCommitDesc (line 2990) | func genCommitDesc(repo *repomgr.Repo, root, parentRoot string) string {
function doPutFile (line 3002) | func doPutFile(repo *repomgr.Repo, rootID, parentDir string, dent *fsmgr...
function putFileRecursive (line 3010) | func putFileRecursive(repo *repomgr.Repo, dirID, toPath string, newDent ...
function updateAPICB (line 3088) | func updateAPICB(rsp http.ResponseWriter, r *http.Request) *appError {
function updateAjaxCB (line 3109) | func updateAjaxCB(rsp http.ResponseWriter, r *http.Request) *appError {
function doUpdate (line 3130) | func doUpdate(rsp http.ResponseWriter, r *http.Request, fsm *recvData, i...
function putFile (line 3269) | func putFile(rsp http.ResponseWriter, r *http.Request, repoID, parentDir...
function formatUpdateJSONRet (line 3411) | func formatUpdateJSONRet(fileName, fileID string, size int64) ([]byte, e...
function checkFileExists (line 3428) | func checkFileExists(storeID, rootID, parentDir, fileName string) (bool,...
function uploadBlksAPICB (line 3447) | func uploadBlksAPICB(rsp http.ResponseWriter, r *http.Request) *appError {
function doUploadBlks (line 3462) | func doUploadBlks(rsp http.ResponseWriter, r *http.Request, fsm *recvDat...
function commitFileBlocks (line 3563) | func commitFileBlocks(repoID, parentDir, fileName, blockIDsJSON, user st...
function checkQuotaBeforeCommitBlocks (line 3640) | func checkQuotaBeforeCommitBlocks(storeID string, blockIDs []string) *ap...
function indexExistedFileBlocks (line 3664) | func indexExistedFileBlocks(repoID string, version int, blkIDs []string,...
function uploadRawBlksAPICB (line 3685) | func uploadRawBlksAPICB(rsp http.ResponseWriter, r *http.Request) *appEr...
function doUploadRawBlks (line 3700) | func doUploadRawBlks(rsp http.ResponseWriter, r *http.Request, fsm *recv...
function postBlocks (line 3755) | func postBlocks(repoID, user string, fsm *recvData) *appError {
function indexRawBlocks (line 3775) | func indexRawBlocks(repoID string, blockIDs []string, fileHeaders []*mul...
type ShareLinkInfo (line 3881) | type ShareLinkInfo struct
function queryShareLinkInfo (line 3888) | func queryShareLinkInfo(token, cookie, opType, ipAddr, userAgent string)...
function accessLinkCB (line 3934) | func accessLinkCB(rsp http.ResponseWriter, r *http.Request) *appError {
function removeFileopExpireCache (line 4194) | func removeFileopExpireCache() {
FILE: fileserver/fileserver.go
function init (line 47) | func init() {
constant timestampFormat (line 63) | timestampFormat = "[2006-01-02 15:04:05] "
type LogFormatter (line 66) | type LogFormatter struct
method Format (line 68) | func (f *LogFormatter) Format(entry *log.Entry) ([]byte, error) {
function loadCcnetDB (line 91) | func loadCcnetDB() {
function registerCA (line 120) | func registerCA(capath string) {
function loadSeafileDB (line 134) | func loadSeafileDB() {
function writePidFile (line 163) | func writePidFile(pid_file_path string) error {
function removePidfile (line 180) | func removePidfile(pid_file_path string) error {
function main (line 188) | func main() {
function handleSignals (line 302) | func handleSignals() {
function handleUser1Signal (line 311) | func handleUser1Signal() {
function logRotate (line 321) | func logRotate() {
function rpcClientInit (line 341) | func rpcClientInit() {
function newHTTPRouter (line 351) | func newHTTPRouter() *mux.Router {
function handleProtocolVersion (line 419) | func handleProtocolVersion(rsp http.ResponseWriter, r *http.Request) {
type appError (line 423) | type appError struct
type appHandler (line 429) | type appHandler
method ServeHTTP (line 431) | func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
function RecoverWrapper (line 440) | func RecoverWrapper(f func()) {
type profileHandler (line 450) | type profileHandler struct
method ServeHTTP (line 454) | func (p *profileHandler) ServeHTTP(w http.ResponseWriter, r *http.Requ...
type traceHandler (line 465) | type traceHandler struct
method ServeHTTP (line 468) | func (p *traceHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques...
FILE: fileserver/fsmgr/fsmgr.go
type Seafile (line 28) | type Seafile struct
method toJSON (line 39) | func (file *Seafile) toJSON() ([]byte, error) {
method FromData (line 476) | func (seafile *Seafile) FromData(p []byte, reader io.ReadCloser) error {
method ToData (line 505) | func (seafile *Seafile) ToData(w io.Writer) error {
function writeField (line 85) | func writeField(buf *bytes.Buffer, key string, value []byte) {
type SeafDirent (line 93) | type SeafDirent struct
method toJSON (line 102) | func (dent *SeafDirent) toJSON() ([]byte, error) {
function jsonNoEscape (line 161) | func jsonNoEscape(data interface{}) ([]byte, error) {
type SeafDir (line 184) | type SeafDir struct
method toJSON (line 192) | func (dir *SeafDir) toJSON() ([]byte, error) {
method ToData (line 520) | func (seafdir *SeafDir) ToData(w io.Writer) error {
method FromData (line 535) | func (seafdir *SeafDir) FromData(p []byte, reader io.ReadCloser) error {
type FileCountInfo (line 231) | type FileCountInfo struct
constant SeafMetadataTypeInvalid (line 239) | SeafMetadataTypeInvalid = iota
constant SeafMetadataTypeFile (line 240) | SeafMetadataTypeFile
constant SeafMetadataTypeLink (line 241) | SeafMetadataTypeLink
constant SeafMetadataTypeDir (line 242) | SeafMetadataTypeDir
constant EmptySha1 (line 249) | EmptySha1 = "0000000000000000000000000000000000000000"
function Init (line 262) | func Init(seafileConfPath string, seafileDataDir string, fsCacheLimit in...
function calCost (line 272) | func calCost(value interface{}) int64 {
constant sizeOfString (line 277) | sizeOfString = int64(unsafe.Sizeof(string("")))
constant sizeOfPointer (line 278) | sizeOfPointer = int64(unsafe.Sizeof(uintptr(0)))
constant sizeOfSeafile (line 279) | sizeOfSeafile = int64(unsafe.Sizeof(Seafile{}))
constant sizeOfSeafDir (line 280) | sizeOfSeafDir = int64(unsafe.Sizeof(SeafDir{}))
constant sizeOfSeafDirent (line 281) | sizeOfSeafDirent = int64(unsafe.Sizeof(SeafDirent{}))
function sizeOf (line 284) | func sizeOf(a interface{}) int64 {
function initZlibReader (line 320) | func initZlibReader() (io.ReadCloser, error) {
function GetOneZlibReader (line 337) | func GetOneZlibReader() io.ReadCloser {
function ReturnOneZlibReader (line 354) | func ReturnOneZlibReader(reader io.ReadCloser) {
function NewDirent (line 364) | func NewDirent(id string, name string, mode uint32, mtime int64, modifie...
function NewSeafdir (line 382) | func NewSeafdir(version int, entries []*SeafDirent) (*SeafDir, error) {
function NewSeafile (line 403) | func NewSeafile(version int, fileSize int64, blkIDs []string) (*Seafile,...
function uncompress (line 425) | func uncompress(p []byte, reader io.ReadCloser) ([]byte, error) {
function compress (line 460) | func compress(p []byte) ([]byte, error) {
function ReadRaw (line 563) | func ReadRaw(repoID string, objID string, w io.Writer) error {
function WriteRaw (line 573) | func WriteRaw(repoID string, objID string, r io.Reader) error {
function GetSeafile (line 582) | func GetSeafile(repoID string, fileID string) (*Seafile, error) {
function GetSeafileWithZlibReader (line 587) | func GetSeafileWithZlibReader(repoID string, fileID string, reader io.Re...
function getSeafile (line 591) | func getSeafile(repoID string, fileID string, reader io.ReadCloser) (*Se...
function SaveSeafile (line 623) | func SaveSeafile(repoID string, seafile *Seafile) error {
function GetSeafdir (line 652) | func GetSeafdir(repoID string, dirID string) (*SeafDir, error) {
function GetSeafdirWithZlibReader (line 657) | func GetSeafdirWithZlibReader(repoID string, dirID string, reader io.Rea...
function getSeafdir (line 661) | func getSeafdir(repoID string, dirID string, reader io.ReadCloser, useCa...
function getSeafdirFromCache (line 702) | func getSeafdirFromCache(repoID string, dirID string) *SeafDir {
function setSeafdirToCache (line 716) | func setSeafdirToCache(repoID string, seafdir *SeafDir) error {
function SaveSeafdir (line 724) | func SaveSeafdir(repoID string, seafdir *SeafDir) error {
function Exists (line 752) | func Exists(repoID string, objID string) (bool, error) {
function comp (line 759) | func comp(c rune) bool {
function IsDir (line 764) | func IsDir(m uint32) bool {
function IsRegular (line 769) | func IsRegular(m uint32) bool {
function GetSeafdirByPath (line 777) | func GetSeafdirByPath(repoID string, rootID string, path string) (*SeafD...
function GetSeafdirIDByPath (line 811) | func GetSeafdirIDByPath(repoID, rootID, path string) (string, error) {
function GetObjIDByPath (line 825) | func GetObjIDByPath(repoID, rootID, path string) (string, uint32, error) {
function GetFileCountInfoByPath (line 867) | func GetFileCountInfoByPath(repoID, rootID, path string) (*FileCountInfo...
function getFileCountInfo (line 883) | func getFileCountInfo(repoID, dirID string) (*FileCountInfo, error) {
function GetDirentByPath (line 912) | func GetDirentByPath(repoID, rootID, rpath string) (*SeafDirent, error) {
FILE: fileserver/fsmgr/fsmgr_test.go
constant seafileConfPath (line 10) | seafileConfPath = "/tmp/conf"
constant seafileDataDir (line 11) | seafileDataDir = "/tmp/conf/seafile-data"
constant repoID (line 12) | repoID = "b1f2ad61-9164-418a-a47f-ab805dbd5694"
constant blkID (line 13) | blkID = "0401fc662e3bc87a41f299a907c056aaf8322a26"
constant subDirID (line 14) | subDirID = "0401fc662e3bc87a41f299a907c056aaf8322a27"
function createFile (line 20) | func createFile() error {
function delFile (line 58) | func delFile() error {
function TestMain (line 67) | func TestMain(m *testing.M) {
function TestGetSeafile (line 82) | func TestGetSeafile(t *testing.T) {
function TestGetSeafdir (line 100) | func TestGetSeafdir(t *testing.T) {
function TestGetSeafdirByPath (line 119) | func TestGetSeafdirByPath(t *testing.T) {
FILE: fileserver/http_code.go
constant seafHTTPResBadFileName (line 4) | seafHTTPResBadFileName = 440
constant seafHTTPResExists (line 5) | seafHTTPResExists = 441
constant seafHTTPResNotExists (line 6) | seafHTTPResNotExists = 441
constant seafHTTPResTooLarge (line 7) | seafHTTPResTooLarge = 442
constant seafHTTPResNoQuota (line 8) | seafHTTPResNoQuota = 443
constant seafHTTPResRepoDeleted (line 9) | seafHTTPResRepoDeleted = 444
constant seafHTTPResRepoCorrupted (line 10) | seafHTTPResRepoCorrupted = 445
constant seafHTTPResBlockMissing (line 11) | seafHTTPResBlockMissing = 446
FILE: fileserver/merge.go
type mergeOptions (line 19) | type mergeOptions struct
function mergeTrees (line 27) | func mergeTrees(storeID string, roots []string, opt *mergeOptions) error {
function mergeTreesRecursive (line 54) | func mergeTreesRecursive(storeID string, trees []*fsmgr.SeafDir, baseDir...
function mergeEntries (line 143) | func mergeEntries(storeID string, dents []*fsmgr.SeafDirent, baseDir str...
function mergeDirectories (line 243) | func mergeDirectories(storeID string, dents []*fsmgr.SeafDirent, baseDir...
function mergeConflictFileName (line 328) | func mergeConflictFileName(storeID string, opt *mergeOptions, baseDir, f...
function genConflictPath (line 350) | func genConflictPath(originPath, modifier string, mtime int64) string {
function getNickNameByModifier (line 376) | func getNickNameByModifier(emailToNickname map[string]string, modifier s...
function postGetNickName (line 397) | func postGetNickName(modifier string) string {
function getFileModifierMtime (line 448) | func getFileModifierMtime(repoID, storeID, head, filePath string) (strin...
FILE: fileserver/merge_test.go
constant mergeTestCommitID (line 15) | mergeTestCommitID = "0401fc662e3bc87a41f299a907c056aaf8322a27"
constant mergeTestRepoID (line 16) | mergeTestRepoID = "b1f2ad61-9164-418a-a47f-ab805dbd5694"
constant mergeTestSeafileConfPath (line 17) | mergeTestSeafileConfPath = "/tmp/conf"
constant mergeTestSeafileDataDir (line 18) | mergeTestSeafileDataDir = "/tmp/conf/seafile-data"
function mergeTestCreateTestDir (line 54) | func mergeTestCreateTestDir() error {
function mergeTestCreateSeafdir (line 194) | func mergeTestCreateSeafdir(dents []*fsmgr.SeafDirent) (string, error) {
function mergeTestDelFile (line 208) | func mergeTestDelFile() error {
function TestMergeTrees (line 217) | func TestMergeTrees(t *testing.T) {
function testMergeTrees1 (line 247) | func testMergeTrees1(t *testing.T) {
function testMergeTrees2 (line 268) | func testMergeTrees2(t *testing.T) {
function testMergeTrees3 (line 289) | func testMergeTrees3(t *testing.T) {
function testMergeTrees4 (line 310) | func testMergeTrees4(t *testing.T) {
function testMergeTrees5 (line 331) | func testMergeTrees5(t *testing.T) {
function testMergeTrees6 (line 351) | func testMergeTrees6(t *testing.T) {
function testMergeTrees7 (line 371) | func testMergeTrees7(t *testing.T) {
function testMergeTrees8 (line 391) | func testMergeTrees8(t *testing.T) {
function testMergeTrees9 (line 411) | func testMergeTrees9(t *testing.T) {
function testMergeTrees10 (line 431) | func testMergeTrees10(t *testing.T) {
function testMergeTrees11 (line 451) | func testMergeTrees11(t *testing.T) {
function testMergeTrees12 (line 471) | func testMergeTrees12(t *testing.T) {
FILE: fileserver/metrics/metrics.go
constant RedisChannel (line 21) | RedisChannel = "metric_channel"
constant ComponentName (line 22) | ComponentName = "go_fileserver"
constant MetricInterval (line 23) | MetricInterval = 30 * time.Second
type MetricMgr (line 26) | type MetricMgr struct
method AddReq (line 37) | func (m *MetricMgr) AddReq(urlPath, method string) *list.Element {
method DecReq (line 50) | func (m *MetricMgr) DecReq(e *list.Element) {
type RequestInfo (line 31) | type RequestInfo struct
function Init (line 64) | func Init() {
function Stop (line 75) | func Stop() {
function metricsHandler (line 82) | func metricsHandler() {
function MetricMiddleware (line 116) | func MetricMiddleware(next http.Handler) http.Handler {
type MetricMessage (line 124) | type MetricMessage struct
function publishMetrics (line 133) | func publishMetrics() error {
function publishRedisMsg (line 159) | func publishRedisMsg(channel string, msg []byte) error {
FILE: fileserver/objstore/backend_fs.go
type fsBackend (line 10) | type fsBackend struct
method read (line 35) | func (b *fsBackend) read(repoID string, objID string, w io.Writer) err...
method write (line 51) | func (b *fsBackend) write(repoID string, objID string, r io.Reader, sy...
method exists (line 94) | func (b *fsBackend) exists(repoID string, objID string) (bool, error) {
method stat (line 106) | func (b *fsBackend) stat(repoID string, objID string) (int64, error) {
function newFSBackend (line 17) | func newFSBackend(seafileDataDir string, objType string) (*fsBackend, er...
FILE: fileserver/objstore/objstore.go
type ObjectStore (line 10) | type ObjectStore struct
method Read (line 39) | func (s *ObjectStore) Read(repoID string, objID string, w io.Writer) (...
method Write (line 44) | func (s *ObjectStore) Write(repoID string, objID string, r io.Reader, ...
method Exists (line 49) | func (s *ObjectStore) Exists(repoID string, objID string) (res bool, e...
method Stat (line 54) | func (s *ObjectStore) Stat(repoID string, objID string) (res int64, er...
type storageBackend (line 18) | type storageBackend interface
function New (line 31) | func New(seafileConfPath string, seafileDataDir string, objType string) ...
FILE: fileserver/objstore/objstore_test.go
constant testFile (line 11) | testFile = "output.data"
constant seafileConfPath (line 12) | seafileConfPath = "/tmp/conf"
constant seafileDataDir (line 13) | seafileDataDir = "/tmp/conf/seafile-data"
constant repoID (line 14) | repoID = "b1f2ad61-9164-418a-a47f-ab805dbd5694"
constant objID (line 15) | objID = "0401fc662e3bc87a41f299a907c056aaf8322a27"
function createFile (line 18) | func createFile() error {
function delFile (line 33) | func delFile() error {
function TestMain (line 47) | func TestMain(m *testing.M) {
function testWrite (line 62) | func testWrite(t *testing.T) {
function testRead (line 73) | func testRead(t *testing.T) {
function testExists (line 87) | func testExists(t *testing.T) {
function TestObjStore (line 101) | func TestObjStore(t *testing.T) {
FILE: fileserver/option/option.go
constant InfiniteQuota (line 16) | InfiniteQuota = -2
constant KB (line 20) | KB = 1000
constant MB (line 21) | MB = 1000000
constant GB (line 22) | GB = 1000000000
constant TB (line 23) | TB = 1000000000000
type DBOption (line 88) | type DBOption struct
function initDefaultOptions (line 102) | func initDefaultOptions() {
function LoadFileServerOptions (line 122) | func LoadFileServerOptions(centralDir string) {
function parseFileServerSection (line 174) | func parseFileServerSection(section *ini.Section) {
function parseQuota (line 254) | func parseQuota(quotaStr string) int64 {
function loadCacheOptionFromEnv (line 296) | func loadCacheOptionFromEnv() {
function LoadSeahubConfig (line 335) | func LoadSeahubConfig() error {
function LoadDBOption (line 351) | func LoadDBOption(centralDir string) (*DBOption, error) {
function loadDBOptionFromFile (line 373) | func loadDBOptionFromFile(centralDir string) (*DBOption, error) {
function loadDBOptionFromEnv (line 439) | func loadDBOptionFromEnv(dbOpt *DBOption) *DBOption {
FILE: fileserver/quota.go
constant InfiniteQuota (line 14) | InfiniteQuota = -2
function checkQuota (line 17) | func checkQuota(repoID string, delta int64) (int, error) {
function getUserQuota (line 64) | func getUserQuota(user string) (int64, error) {
function getUserUsage (line 83) | func getUserUsage(user string) (int64, error) {
FILE: fileserver/repomgr/repomgr.go
constant RepoStatusNormal (line 19) | RepoStatusNormal = iota
constant RepoStatusReadOnly (line 20) | RepoStatusReadOnly
constant NRepoStatus (line 21) | NRepoStatus
type Repo (line 25) | type Repo struct
type VRepoInfo (line 54) | type VRepoInfo struct
function Init (line 64) | func Init(seafDB *sql.DB) {
function Get (line 69) | func Get(id string) *Repo {
function RepoToCommit (line 168) | func RepoToCommit(repo *Repo, commit *commitmgr.Commit) {
function GetEx (line 200) | func GetEx(id string) *Repo {
function GetVirtualRepoInfo (line 301) | func GetVirtualRepoInfo(repoID string) (*VRepoInfo, error) {
function GetVirtualRepoInfoByOrigin (line 318) | func GetVirtualRepoInfoByOrigin(originRepo string) ([]*VRepoInfo, error) {
function GetEmailByToken (line 343) | func GetEmailByToken(repoID string, token string) (string, error) {
function GetRepoStatus (line 359) | func GetRepoStatus(repoID string) (int, error) {
function TokenPeerInfoExists (line 393) | func TokenPeerInfoExists(token string) (bool, error) {
function AddTokenPeerInfo (line 410) | func AddTokenPeerInfo(token, peerID, peerIP, peerName, clientVer string,...
function UpdateTokenPeerInfo (line 423) | func UpdateTokenPeerInfo(token, peerID, clientVer string, syncTime int64...
function GetUploadTmpFile (line 435) | func GetUploadTmpFile(repoID, filePath string) (string, error) {
function AddUploadTmpFile (line 468) | func AddUploadTmpFile(repoID, filePath, tmpFile string) error {
function DelUploadTmpFile (line 486) | func DelUploadTmpFile(repoID, filePath string) error {
function setRepoCommitToDb (line 507) | func setRepoCommitToDb(repoID, repoName string, updateTime int64, versio...
function SetVirtualRepoBaseCommitPath (line 546) | func SetVirtualRepoBaseCommitPath(repoID, baseCommitID, newPath string) ...
function GetVirtualRepoIDsByOrigin (line 557) | func GetVirtualRepoIDsByOrigin(repoID string) ([]string, error) {
function DelVirtualRepo (line 582) | func DelVirtualRepo(repoID string, cloudMode bool) error {
function removeVirtualRepoOndisk (line 599) | func removeVirtualRepoOndisk(repoID string, cloudMode bool) error {
function IsVirtualRepo (line 701) | func IsVirtualRepo(repoID string) (bool, error) {
function GetRepoOwner (line 719) | func GetRepoOwner(repoID string) (string, error) {
function UpdateRepoInfo (line 735) | func UpdateRepoInfo(repoID, commitID string) error {
function HasLastGCID (line 747) | func HasLastGCID(repoID, clientID string) (bool, error) {
function GetLastGCID (line 765) | func GetLastGCID(repoID, clientID string) (string, error) {
function GetCurrentGCID (line 781) | func GetCurrentGCID(repoID string) (string, error) {
function RemoveLastGCID (line 797) | func RemoveLastGCID(repoID, clientID string) error {
function SetLastGCID (line 807) | func SetLastGCID(repoID, clientID, gcID string) error {
FILE: fileserver/repomgr/repomgr_test.go
constant user (line 16) | user = "seafile"
constant password (line 17) | password = "seafile"
constant host (line 18) | host = "127.0.0.1"
constant port (line 19) | port = 3306
constant dbName (line 20) | dbName = "seafile-db"
constant useTLS (line 21) | useTLS = false
constant seafileConfPath (line 22) | seafileConfPath = "/root/conf"
constant seafileDataDir (line 23) | seafileDataDir = "/root/conf/seafile-data"
constant repoName (line 24) | repoName = "repo"
constant userName (line 25) | userName = "seafile@seafile.com"
constant encVersion (line 26) | encVersion = 2
constant pipePath (line 27) | pipePath = "/root/runtime/seafile.sock"
constant service (line 28) | service = "seafserv-threaded-rpcserver"
function createRepo (line 34) | func createRepo() string {
function delRepo (line 51) | func delRepo() {
function TestMain (line 59) | func TestMain(m *testing.M) {
function TestGet (line 74) | func TestGet(t *testing.T) {
FILE: fileserver/searpc/searpc.go
type Client (line 14) | type Client struct
method Call (line 44) | func (c *Client) Call(funcname string, params ...interface{}) (interfa...
method getConn (line 140) | func (c *Client) getConn() (*net.UnixConn, error) {
method returnConn (line 159) | func (c *Client) returnConn(conn *net.UnixConn) {
type request (line 24) | type request struct
function Init (line 30) | func Init(pipePath string, service string, maxConn int) *Client {
FILE: fileserver/searpc/searpc_test.go
constant repoName (line 9) | repoName = "repo"
constant userName (line 10) | userName = "seafile@seafile.com"
constant encVersion (line 11) | encVersion = 2
constant pipePath (line 12) | pipePath = "/root/runtime/seafile.sock"
constant service (line 13) | service = "seafserv-threaded-rpcserver"
function TestMain (line 18) | func TestMain(m *testing.M) {
function TestCallRpc (line 24) | func TestCallRpc(t *testing.T) {
FILE: fileserver/share/share.go
type group (line 18) | type group struct
function Init (line 32) | func Init(cnDB *sql.DB, seafDB *sql.DB, grpTableName string, clMode bool) {
function CheckPerm (line 40) | func CheckPerm(repoID string, user string) string {
function checkVirtualRepoPerm (line 56) | func checkVirtualRepoPerm(repoID, originRepoID, user, vPath string) stri...
function getUserGroups (line 74) | func getUserGroups(sqlStr string, args ...interface{}) ([]group, error) {
function getGroupsByUser (line 101) | func getGroupsByUser(userName string, returnAncestors bool) ([]group, er...
function getGroupPaths (line 153) | func getGroupPaths(sqlStr string) (string, error) {
function checkGroupPermByUser (line 180) | func checkGroupPermByUser(repoID string, userName string) (string, error) {
function checkSharedRepoPerm (line 229) | func checkSharedRepoPerm(repoID string, email string) (string, error) {
function checkInnerPubRepoPerm (line 245) | func checkInnerPubRepoPerm(repoID string) (string, error) {
function checkRepoSharePerm (line 262) | func checkRepoSharePerm(repoID string, userName string) string {
function getSharedDirsToUser (line 296) | func getSharedDirsToUser(originRepoID string, toEmail string) (map[strin...
function getDirPerm (line 326) | func getDirPerm(perms map[string]string, path string) string {
function convertGroupListToStr (line 340) | func convertGroupListToStr(groups []group) string {
function getSharedDirsToGroup (line 352) | func getSharedDirsToGroup(originRepoID string, groups []group) (map[stri...
function checkPermOnParentRepo (line 387) | func checkPermOnParentRepo(originRepoID, user, vPath string) string {
type SharedRepo (line 424) | type SharedRepo struct
function GetReposByOwner (line 437) | func GetReposByOwner(email string) ([]*SharedRepo, error) {
function ListInnerPubRepos (line 497) | func ListInnerPubRepos() ([]*SharedRepo, error) {
function ListShareRepos (line 551) | func ListShareRepos(email, columnType string) ([]*SharedRepo, error) {
function GetGroupReposByUser (line 623) | func GetGroupReposByUser(user string, orgID int) ([]*SharedRepo, error) {
FILE: fileserver/size_sched.go
constant RepoSizeList (line 26) | RepoSizeList = "repo_size_task"
function sizeSchedulerInit (line 32) | func sizeSchedulerInit() {
function computeRepoSize (line 65) | func computeRepoSize(args ...interface{}) error {
function setRepoSizeAndFileCount (line 149) | func setRepoSizeAndFileCount(repoID, newHeadID string, size, fileCount i...
type RepoSizeChangeTask (line 216) | type RepoSizeChangeTask struct
function notifyRepoSizeChange (line 220) | func notifyRepoSizeChange(repoID string) error {
type RepoInfo (line 244) | type RepoInfo struct
function getOldRepoInfo (line 250) | func getOldRepoInfo(repoID string) (*RepoInfo, error) {
FILE: fileserver/sync_api.go
type checkExistType (line 33) | type checkExistType
constant checkFSExist (line 36) | checkFSExist checkExistType = 0
constant checkBlockExist (line 37) | checkBlockExist checkExistType = 1
constant seafileServerChannelEvent (line 41) | seafileServerChannelEvent = "seaf_server.event"
constant seafileServerChannelStats (line 42) | seafileServerChannelStats = "seaf_server.stats"
constant emptySHA1 (line 43) | emptySHA1 = "0000000000000000000000000000000000000000"
constant tokenExpireTime (line 44) | tokenExpireTime = 7200
constant permExpireTime (line 45) | permExpireTime = 7200
constant virtualRepoExpireTime (line 46) | virtualRepoExpireTime = 7200
constant syncAPICleaningIntervalSec (line 47) | syncAPICleaningIntervalSec = 300
constant maxObjectPackSize (line 48) | maxObjectPackSize = 1 << 20
constant fsIdWorkers (line 49) | fsIdWorkers = 10
type tokenInfo (line 59) | type tokenInfo struct
type permInfo (line 65) | type permInfo struct
type virtualRepoInfo (line 70) | type virtualRepoInfo struct
type repoEventData (line 75) | type repoEventData struct
type statsEventData (line 84) | type statsEventData struct
function syncAPIInit (line 91) | func syncAPIInit() {
type calResult (line 102) | type calResult struct
function getFsId (line 107) | func getFsId(args ...interface{}) error {
function permissionCheckCB (line 194) | func permissionCheckCB(rsp http.ResponseWriter, r *http.Request) *appErr...
function getBlockMapCB (line 275) | func getBlockMapCB(rsp http.ResponseWriter, r *http.Request) *appError {
function getAccessibleRepoListCB (line 329) | func getAccessibleRepoListCB(rsp http.ResponseWriter, r *http.Request) *...
function filterGroupRepos (line 434) | func filterGroupRepos(repos []*share.SharedRepo) map[string]*share.Share...
function recvFSCB (line 453) | func recvFSCB(rsp http.ResponseWriter, r *http.Request) *appError {
function checkFSCB (line 511) | func checkFSCB(rsp http.ResponseWriter, r *http.Request) *appError {
function checkBlockCB (line 515) | func checkBlockCB(rsp http.ResponseWriter, r *http.Request) *appError {
function postCheckExistCB (line 519) | func postCheckExistCB(rsp http.ResponseWriter, r *http.Request, existTyp...
function packFSCB (line 576) | func packFSCB(rsp http.ResponseWriter, r *http.Request) *appError {
function headCommitsMultiCB (line 630) | func headCommitsMultiCB(rsp http.ResponseWriter, r *http.Request) *appEr...
function getCheckQuotaCB (line 693) | func getCheckQuotaCB(rsp http.ResponseWriter, r *http.Request) *appError {
function getJWTTokenCB (line 728) | func getJWTTokenCB(rsp http.ResponseWriter, r *http.Request) *appError {
function getFsObjIDCB (line 754) | func getFsObjIDCB(rsp http.ResponseWriter, r *http.Request) *appError {
function headCommitOperCB (line 762) | func headCommitOperCB(rsp http.ResponseWriter, r *http.Request) *appError {
function commitOperCB (line 771) | func commitOperCB(rsp http.ResponseWriter, r *http.Request) *appError {
function blockOperCB (line 780) | func blockOperCB(rsp http.ResponseWriter, r *http.Request) *appError {
function putSendBlockCB (line 789) | func putSendBlockCB(rsp http.ResponseWriter, r *http.Request) *appError {
function getBlockInfo (line 820) | func getBlockInfo(rsp http.ResponseWriter, r *http.Request) *appError {
function getRepoStoreID (line 863) | func getRepoStoreID(repoID string) (string, error) {
function sendStatisticMsg (line 906) | func sendStatisticMsg(repoID, user, operation string, bytes uint64) {
function publishStatsEvent (line 912) | func publishStatsEvent(rData *statsEventData) {
function saveLastGCID (line 928) | func saveLastGCID(repoID, token string) error {
function putCommitCB (line 940) | func putCommitCB(rsp http.ResponseWriter, r *http.Request) *appError {
function getCommitInfo (line 985) | func getCommitInfo(rsp http.ResponseWriter, r *http.Request) *appError {
function putUpdateBranchCB (line 1016) | func putUpdateBranchCB(rsp http.ResponseWriter, r *http.Request) *appErr...
type checkBlockAux (line 1096) | type checkBlockAux struct
function checkBlocks (line 1102) | func checkBlocks(ctx context.Context, repo *repomgr.Repo, base, remote *...
function checkFileBlocks (line 1127) | func checkFileBlocks(ctx context.Context, baseDir string, files []*fsmgr...
function checkDirCB (line 1161) | func checkDirCB(ctx context.Context, baseDir string, dirs []*fsmgr.SeafD...
function includeInvalidPath (line 1196) | func includeInvalidPath(baseCommit, newCommit *commitmgr.Commit) bool {
function getHeadCommit (line 1218) | func getHeadCommit(rsp http.ResponseWriter, r *http.Request) *appError {
function checkPermission (line 1266) | func checkPermission(repoID, user, op string, skipCache bool) *appError {
function validateToken (line 1305) | func validateToken(r *http.Request, repoID string, skipCache bool) (stri...
function validateClientVer (line 1348) | func validateClientVer(clientVer string) int {
function getClientIPAddr (line 1366) | func getClientIPAddr(r *http.Request) string {
function onRepoOper (line 1390) | func onRepoOper(eType, repoID, user, ip, clientName string) {
function publishRepoEvent (line 1412) | func publishRepoEvent(rData *repoEventData) {
function publishUpdateEvent (line 1433) | func publishUpdateEvent(repoID string, commitID string) {
function removeSyncAPIExpireCache (line 1448) | func removeSyncAPIExpireCache() {
type collectFsInfo (line 1481) | type collectFsInfo struct
function calculateSendObjectList (line 1489) | func calculateSendObjectList(ctx context.Context, repo *repomgr.Repo, se...
function collectFileIDs (line 1539) | func collectFileIDs(ctx context.Context, baseDir string, files []*fsmgr....
function collectFileIDsNOp (line 1563) | func collectFileIDsNOp(ctx context.Context, baseDir string, files []*fsm...
function collectDirIDs (line 1567) | func collectDirIDs(ctx context.Context, baseDir string, dirs []*fsmgr.Se...
FILE: fileserver/utils/dup2.go
function Dup (line 9) | func Dup(from, to int) error {
FILE: fileserver/utils/dup3.go
function Dup (line 9) | func Dup(from, to int) error {
FILE: fileserver/utils/http.go
function GetAuthorizationToken (line 13) | func GetAuthorizationToken(h http.Header) string {
function HttpCommon (line 22) | func HttpCommon(method, url string, header map[string][]string, reader i...
function parseErrorMessage (line 52) | func parseErrorMessage(r io.Reader) []byte {
FILE: fileserver/utils/utils.go
function IsValidUUID (line 12) | func IsValidUUID(u string) bool {
function IsObjectIDValid (line 17) | func IsObjectIDValid(objID string) bool {
type SeahubClaims (line 31) | type SeahubClaims struct
method Valid (line 37) | func (*SeahubClaims) Valid() error {
function GenSeahubJWTToken (line 41) | func GenSeahubJWTToken() (string, error) {
type MyClaims (line 56) | type MyClaims struct
method Valid (line 63) | func (*MyClaims) Valid() error {
function GenNotifJWTToken (line 67) | func GenNotifJWTToken(repoID, user string, exp int64) (string, error) {
FILE: fileserver/virtual_repo.go
constant mergeVirtualRepoWorkerNumber (line 22) | mergeVirtualRepoWorkerNumber = 5
function virtualRepoInit (line 29) | func virtualRepoInit() {
function mergeVirtualRepo (line 33) | func mergeVirtualRepo(args ...interface{}) error {
function mergeRepo (line 100) | func mergeRepo(repoID string) error {
function cleanupVirtualRepos (line 204) | func cleanupVirtualRepos(repoID string) error {
function handleMissingVirtualRepo (line 234) | func handleMissingVirtualRepo(repo *repomgr.Repo, head *commitmgr.Commit...
function editRepo (line 306) | func editRepo(repoID, name, desc, user string) error {
function editRepoNeedRetry (line 331) | func editRepoNeedRetry(repoID, name, desc, user string) (bool, error) {
FILE: fileserver/workerpool/workerpool.go
type WorkPool (line 10) | type WorkPool struct
method AddTask (line 35) | func (pool *WorkPool) AddTask(args ...interface{}) {
method run (line 40) | func (pool *WorkPool) run(jobs chan Job) {
method Shutdown (line 63) | func (pool *WorkPool) Shutdown() {
type Job (line 17) | type Job struct
type JobCB (line 22) | type JobCB
function CreateWorkerPool (line 24) | func CreateWorkerPool(jobCB JobCB, n int) *WorkPool {
FILE: fuse/file.c
function read_file (line 16) | int read_file(SeafileSession *seaf,
FILE: fuse/getattr.c
function CcnetEmailUser (line 18) | static CcnetEmailUser *get_user_from_ccnet (SearpcClient *client, const ...
function getattr_root (line 25) | static int getattr_root(SeafileSession *seaf, struct stat *stbuf)
function getattr_user (line 34) | static int getattr_user(SeafileSession *seaf, const char *user, struct s...
function getattr_repo (line 51) | static int getattr_repo(SeafileSession *seaf,
function do_getattr (line 151) | int do_getattr(SeafileSession *seaf, const char *path, struct stat *stbuf)
FILE: fuse/readdir.c
function GList (line 30) | static GList *get_users_from_ccnet (SearpcClient *client, const char *so...
function CcnetEmailUser (line 37) | static CcnetEmailUser *get_user_from_ccnet (SearpcClient *client, const ...
function readdir_root (line 44) | static int readdir_root(SeafileSession *seaf,
function readdir_user (line 89) | static int readdir_user(SeafileSession *seaf, const char *user,
function readdir_repo (line 138) | static int readdir_repo(SeafileSession *seaf,
function do_readdir (line 190) | int do_readdir(SeafileSession *seaf, const char *path, void *buf,
FILE: fuse/repo-mgr.c
type _SeafRepoManagerPriv (line 20) | struct _SeafRepoManagerPriv {
function gboolean (line 27) | gboolean
function SeafRepo (line 36) | SeafRepo*
function seaf_repo_free (line 56) | void
function seaf_repo_ref (line 66) | void
function seaf_repo_unref (line 72) | void
function set_head_common (line 82) | static void
function seaf_repo_from_commit (line 91) | void
function seaf_repo_to_commit (line 101) | void
function gboolean (line 111) | static gboolean
function GList (line 123) | GList *
function compare_repo (line 164) | static int
function SeafRepoManager (line 171) | SeafRepoManager*
function seaf_repo_manager_init (line 182) | int
function seaf_repo_manager_start (line 188) | int
function gboolean (line 194) | static gboolean
function SeafRepo (line 205) | SeafRepo*
function gboolean (line 227) | gboolean
function load_repo_commit (line 236) | static void
function gboolean (line 258) | static gboolean
function SeafRepo (line 289) | static SeafRepo *
function gboolean (line 328) | static gboolean
function GList (line 340) | GList *
function GList (line 355) | GList *
function GList (line 383) | GList *
function gboolean (line 410) | gboolean
FILE: fuse/repo-mgr.h
type _SeafRepoManager (line 12) | struct _SeafRepoManager
type SeafRepo (line 13) | typedef struct _SeafRepo SeafRepo;
type _SeafRepo (line 15) | struct _SeafRepo {
type SeafRepoManager (line 57) | typedef struct _SeafRepoManager SeafRepoManager;
type SeafRepoManagerPriv (line 58) | typedef struct _SeafRepoManagerPriv SeafRepoManagerPriv;
type _SeafRepoManager (line 60) | struct _SeafRepoManager {
type _SeafileSession (line 67) | struct _SeafileSession
FILE: fuse/seaf-fuse.c
function parse_fuse_path (line 36) | int parse_fuse_path (const char *path,
function seaf_fuse_getattr (line 84) | static int seaf_fuse_getattr(const char *path, struct stat *stbuf)
function seaf_fuse_readdir (line 90) | static int seaf_fuse_readdir(const char *path, void *buf,
function seaf_fuse_open (line 100) | static int seaf_fuse_open(const char *path, struct fuse_file_info *info)
function seaf_fuse_read (line 166) | static int seaf_fuse_read(const char *path, char *buf, size_t size,
type options (line 242) | struct options {
type fuse_opt (line 256) | struct fuse_opt
type fuse_operations (line 273) | struct fuse_operations
function main (line 280) | int main(int argc, char *argv[])
FILE: fuse/seaf-fuse.h
type fuse_file_info (line 19) | struct fuse_file_info
type stat (line 22) | struct stat
type fuse_file_info (line 27) | struct fuse_file_info
FILE: fuse/seafile-session.c
function SeafileSession (line 18) | SeafileSession *
function read_excluded_users (line 125) | static int
function seafile_session_init (line 153) | int
function seafile_session_start (line 181) | int
FILE: fuse/seafile-session.h
type SeafileSession (line 18) | typedef struct _SeafileSession SeafileSession;
type _SeafileSession (line 20) | struct _SeafileSession {
FILE: lib/bloom-filter.c
function Bloom (line 15) | Bloom* bloom_create(size_t size, int k, int counting)
function bloom_destroy (line 45) | int bloom_destroy(Bloom *bloom)
function incr_bit (line 54) | static void
function decr_bit (line 85) | static void
function bloom_add (line 124) | int bloom_add(Bloom *bloom, const char *s)
function bloom_remove (line 141) | int bloom_remove(Bloom *bloom, const char *s)
function bloom_test (line 161) | int bloom_test(Bloom *bloom, const char *s)
FILE: lib/bloom-filter.h
type Bloom (line 8) | typedef struct {
FILE: lib/db.c
function sqlite_open_db (line 7) | int
function sqlite_close_db (line 27) | int sqlite_close_db (sqlite3 *db)
function sqlite3_stmt (line 32) | sqlite3_stmt *
function sqlite_query_exec (line 52) | int
function sqlite_begin_transaction (line 71) | int
function sqlite_end_transaction (line 78) | int
function gboolean (line 86) | gboolean
function sqlite_foreach_selected_row (line 112) | int
function sqlite_get_int (line 147) | int sqlite_get_int (sqlite3 *db, const char *sql)
function gint64 (line 175) | gint64 sqlite_get_int64 (sqlite3 *db, const char *sql)
FILE: lib/db.h
type gboolean (line 20) | typedef gboolean (*SqliteRowFunc) (sqlite3_stmt *stmt, void *data);
FILE: lib/job-mgr.c
type _CcnetJob (line 22) | struct _CcnetJob {
function job_thread_wrapper (line 40) | static void
function job_done_cb (line 52) | static void
function job_thread_create (line 70) | int
function CcnetJob (line 87) | CcnetJob *
function ccnet_job_free (line 96) | void
function CcnetJobManager (line 102) | CcnetJobManager *
function ccnet_job_manager_free (line 120) | void
function ccnet_job_manager_schedule_job (line 128) | int
function ccnet_job_manager_remove_job (line 151) | void
function ccnet_job_manager_wait_job (line 158) | void
FILE: lib/job-mgr.h
type _CcnetSession (line 13) | struct _CcnetSession
type CcnetJob (line 15) | typedef struct _CcnetJob CcnetJob;
type CcnetJobManager (line 16) | typedef struct _CcnetJobManager CcnetJobManager;
type _CcnetJobManager (line 27) | struct _CcnetJobManager {
FILE: lib/net.c
function inet_aton (line 46) | int inet_aton(const char *string, struct in_addr *addr)
function ccnet_netSetTOS (line 57) | int
function evutil_socket_t (line 67) | static evutil_socket_t
function evutil_socket_t (line 83) | static evutil_socket_t
function evutil_socket_t (line 110) | evutil_socket_t
function evutil_socket_t (line 145) | evutil_socket_t
function ccnet_net_make_socket_blocking (line 231) | int
function evutil_socket_t (line 258) | evutil_socket_t
function evutil_socket_t (line 275) | evutil_socket_t
type sockaddr (line 327) | struct sockaddr
type sockaddr_in (line 333) | struct sockaddr_in
type sockaddr_in (line 333) | struct sockaddr_in
type sockaddr_in6 (line 342) | struct sockaddr_in6
type sockaddr_in6 (line 342) | struct sockaddr_in6
type sockaddr_un (line 353) | struct sockaddr_un
type sockaddr_un (line 353) | struct sockaddr_un
function sock_pton (line 374) | int
function is_valid_ipaddr (line 401) | int
function sock_port (line 412) | uint16_t
function evutil_socket_t (line 434) | evutil_socket_t
function family_to_level (line 475) | int
function mcast_join (line 491) | static int
function evutil_socket_t (line 519) | evutil_socket_t
function mcast_join (line 563) | static int
function evutil_socket_t (line 656) | evutil_socket_t
function sockfd_to_family (line 693) | int
function mcast_set_loop (line 705) | int
FILE: lib/net.h
type socklen_t (line 9) | typedef int socklen_t;
type in_addr (line 42) | struct in_addr
type sockaddr (line 47) | struct sockaddr
type sockaddr_storage (line 50) | struct sockaddr_storage
type sockaddr (line 60) | struct sockaddr
type sockaddr (line 61) | struct sockaddr
type sockaddr_storage (line 69) | struct sockaddr_storage
type sockaddr (line 72) | struct sockaddr
type sockaddr (line 76) | struct sockaddr
FILE: lib/timer.c
type CcnetTimer (line 17) | struct CcnetTimer
function timer_callback (line 26) | static void
function ccnet_timer_free (line 42) | void
function CcnetTimer (line 61) | CcnetTimer*
FILE: lib/timer.h
type CcnetTimer (line 9) | struct CcnetTimer
type CcnetTimer (line 11) | typedef struct CcnetTimer CcnetTimer;
FILE: lib/utils.c
function timeval_from_msec (line 62) | struct timeval
function rawdata_to_hex (line 72) | void
function hexval (line 86) | static unsigned hexval(char c)
function hex_to_rawdata (line 97) | int
function ccnet_strlcpy (line 111) | size_t
function checkdir (line 125) | int
function checkdir_with_mkdir (line 148) | int
function objstore_mkdir (line 164) | int
function objstore_get_path (line 191) | void
function __time64_t (line 212) | __time64_t
function get_utc_file_time_fd (line 223) | static int
function unix_time_to_file_time (line 248) | inline static void
function set_utc_file_time (line 258) | static int
function wchar_t (line 288) | wchar_t *
function wchar_t (line 309) | wchar_t *
function windows_error_to_errno (line 365) | static int
function seaf_stat (line 386) | int
function seaf_fstat (line 422) | int
function seaf_stat_from_find_data (line 440) | void
function seaf_set_file_time (line 459) | int
function seaf_util_unlink (line 487) | int
function seaf_util_rmdir (line 506) | int
function seaf_util_mkdir (line 525) | int
function seaf_util_open (line 544) | int
function seaf_util_create (line 581) | int
function seaf_util_rename (line 618) | int
function gboolean (line 639) | gboolean
function gint64 (line 657) | gint64
function traverse_directory_win32 (line 669) | int
function readn (line 735) | ssize_t
function writen (line 760) | ssize_t
function recvn (line 785) | ssize_t
function sendn (line 814) | ssize_t
function copy_fd (line 842) | int copy_fd (int ifd, int ofd)
function copy_file (line 862) | int copy_file (const char *dst, const char *src, int mode)
type passwd (line 936) | struct passwd
function calculate_sha1 (line 1016) | int
function ccnet_sha1_hash (line 1030) | uint32_t
function ccnet_sha1_equal (line 1044) | int
function gen_uuid_inplace (line 1071) | void gen_uuid_inplace (char *buf)
function gboolean (line 1079) | gboolean
function gen_uuid_inplace (line 1106) | void gen_uuid_inplace (char *buf)
function gboolean (line 1117) | gboolean
function gboolean (line 1131) | gboolean
function gboolean (line 1175) | gboolean is_ipaddr_valid (const char *ip)
function parse_key_value_pairs (line 1188) | void parse_key_value_pairs (char *string, KeyValueFunc func, void *data)
function parse_key_value_pairs2 (line 1218) | void parse_key_value_pairs2 (char *string, KeyValueFunc2 func, void *data)
function gboolean (line 1258) | gboolean
function GList (line 1278) | GList*
function GList (line 1290) | GList *
function GList (line 1304) | GList *
function string_list_free (line 1321) | void
function string_list_join (line 1335) | void
function GList (line 1351) | GList *
function GList (line 1370) | GList *
function gboolean (line 1378) | gboolean
function nfree_string_array (line 1407) | void
function gint64 (line 1417) | gint64
type sockaddr_in (line 1425) | struct sockaddr_in
function pgpipe (line 1430) | int
function ccnet_encrypt (line 1525) | int
function ccnet_decrypt (line 1640) | int
function HANDLE (line 1800) | static HANDLE
function count_process (line 1845) | int count_process (const char *process_name_in)
function gboolean (line 1892) | gboolean
function win32_kill_process (line 1905) | int
function win32_spawn_process (line 1919) | int
function wchar_t (line 2022) | wchar_t *
function find_process_in_dirent (line 2067) | static int
function gboolean (line 2096) | gboolean process_is_running (const char *process_name)
function count_process (line 2121) | int count_process(const char *process_name)
function gboolean (line 2148) | gboolean process_is_running (const char *process_name)
function win_stat64_utf8 (line 2175) | static inline int
function gint64 (line 2189) | static gint64
function gint64 (line 2233) | gint64
function gboolean (line 2287) | gboolean
function gint64 (line 2293) | gint64
function json_object_set_string_member (line 2300) | void
function json_object_set_int_member (line 2306) | void
function clean_utf8_data (line 2312) | void
function seaf_compress (line 2347) | int
function seaf_decompress (line 2389) | int
function gboolean (line 2464) | gboolean
function gboolean (line 2470) | gboolean
function gchar (line 2497) | gchar*
FILE: lib/utils.h
type timeval (line 154) | struct timeval
type gboolean (line 212) | typedef gboolean (*KeyValueFunc2) (void *data, const char *key,
function bswap64 (line 254) | static inline uint64_t
function hton64 (line 272) | static inline uint64_t
function ntoh64 (line 282) | static inline uint64_t
function put64bit (line 292) | static inline void put64bit(uint8_t **ptr,uint64_t val)
function put32bit (line 299) | static inline void put32bit(uint8_t **ptr,uint32_t val)
function put16bit (line 306) | static inline void put16bit(uint8_t **ptr,uint16_t val)
function get64bit (line 313) | static inline uint64_t get64bit(const uint8_t **ptr)
function get32bit (line 320) | static inline uint32_t get32bit(const uint8_t **ptr)
function get16bit (line 327) | static inline uint16_t get16bit(const uint8_t **ptr)
FILE: notification-server/client.go
constant writeWait (line 15) | writeWait = 1 * time.Second
constant pongWait (line 16) | pongWait = 5 * time.Second
constant pingPeriod (line 18) | pingPeriod = 1 * time.Second
constant checkTokenPeriod (line 20) | checkTokenPeriod = 1 * time.Hour
type Message (line 24) | type Message struct
type SubList (line 29) | type SubList struct
type UnsubList (line 33) | type UnsubList struct
type Repo (line 37) | type Repo struct
type myClaims (line 42) | type myClaims struct
method Valid (line 49) | func (*myClaims) Valid() error {
method Close (line 53) | func (client *Client) Close() {
function RecoverWrapper (line 57) | func RecoverWrapper(f func()) {
method HandleMessages (line 68) | func (client *Client) HandleMessages() {
method readMessages (line 88) | func (client *Client) readMessages() {
function checkToken (line 117) | func checkToken(tokenString, repoID string) (string, int64, bool) {
method handleMessage (line 141) | func (client *Client) handleMessage(msg *Message) error {
method subscribe (line 176) | func (client *Client) subscribe(repoID, user string, exp int64) {
method unsubscribe (line 196) | func (client *Client) unsubscribe(repoID string) {
method writeMessages (line 215) | func (client *Client) writeMessages() {
method keepAlive (line 240) | func (client *Client) keepAlive() {
method checkTokenExpired (line 269) | func (client *Client) checkTokenExpired() {
method notifJWTExpired (line 300) | func (client *Client) notifJWTExpired(repoID string) {
FILE: notification-server/dup2.go
function Dup (line 9) | func Dup(from, to int) error {
FILE: notification-server/dup3.go
function Dup (line 9) | func Dup(from, to int) error {
FILE: notification-server/event.go
type RepoUpdateEvent (line 13) | type RepoUpdateEvent struct
type FileLockEvent (line 18) | type FileLockEvent struct
type FolderPermEvent (line 25) | type FolderPermEvent struct
type CommentEvent (line 35) | type CommentEvent struct
function Notify (line 42) | func Notify(msg *Message) {
function getGroupMembers (line 132) | func getGroupMembers(group int) map[string]struct{} {
function needToNotif (line 167) | func needToNotif(userList map[string]struct{}, user string) bool {
FILE: notification-server/logger.go
constant timestampFormat (line 11) | timestampFormat = "[2006-01-02 15:04:05] "
type LogFormatter (line 14) | type LogFormatter struct
method Format (line 16) | func (f *LogFormatter) Format(entry *log.Entry) ([]byte, error) {
FILE: notification-server/server.go
function init (line 36) | func init() {
function loadNotifConfig (line 48) | func loadNotifConfig() {
function loadCcnetDB (line 76) | func loadCcnetDB() {
type DBOption (line 100) | type DBOption struct
function loadDBOptionFromEnv (line 111) | func loadDBOptionFromEnv() (*DBOption, error) {
function main (line 159) | func main() {
function loadJwtPrivateKey (line 223) | func loadJwtPrivateKey() error {
function handleUser1Signal (line 232) | func handleUser1Signal() {
function logRotate (line 242) | func logRotate() {
function newHTTPRouter (line 259) | func newHTTPRouter() *mux.Router {
function messageCB (line 269) | func messageCB(rsp http.ResponseWriter, r *http.Request) *appError {
function eventCB (line 289) | func eventCB(rsp http.ResponseWriter, r *http.Request) *appError {
function getAuthorizationToken (line 320) | func getAuthorizationToken(h http.Header) string {
function checkAuthToken (line 329) | func checkAuthToken(tokenString string) bool {
function newUpgrader (line 350) | func newUpgrader() *websocket.Upgrader {
function pingCB (line 362) | func pingCB(rsp http.ResponseWriter, r *http.Request) *appError {
type appError (line 367) | type appError struct
type appHandler (line 373) | type appHandler
method ServeHTTP (line 375) | func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
FILE: notification-server/subscriptions.go
constant chanBufSize (line 13) | chanBufSize = 10
type Client (line 32) | type Client struct
type Subscribers (line 57) | type Subscribers struct
function Init (line 64) | func Init() {
function NewClient (line 70) | func NewClient(conn *websocket.Conn, addr string) *Client {
function RegisterClient (line 84) | func RegisterClient(client *Client) {
function UnregisterClient (line 91) | func UnregisterClient(client *Client) {
function newSubscribers (line 97) | func newSubscribers(client *Client) *Subscribers {
FILE: python/seafile/__init__.py
class TaskType (line 3) | class TaskType(object):
FILE: python/seafile/rpcclient.py
class SeafServerThreadedRpcClient (line 3) | class SeafServerThreadedRpcClient(NamedPipeClient):
method __init__ (line 5) | def __init__(self, pipe_path):
method seafile_create_repo (line 10) | def seafile_create_repo(name, desc, owner_email, passwd, enc_version, ...
method seafile_create_enc_repo (line 15) | def seafile_create_enc_repo(repo_id, name, desc, owner_email, magic, r...
method seafile_get_repos_by_id_prefix (line 20) | def seafile_get_repos_by_id_prefix(id_prefix, start, limit):
method seafile_get_repo (line 25) | def seafile_get_repo(repo_id):
method seafile_destroy_repo (line 30) | def seafile_destroy_repo(repo_id):
method seafile_get_repo_list (line 35) | def seafile_get_repo_list(start, limit, order_by, ret_virt_repo):
method seafile_count_repos (line 40) | def seafile_count_repos():
method seafile_edit_repo (line 45) | def seafile_edit_repo(repo_id, name, description, user):
method seafile_is_repo_owner (line 50) | def seafile_is_repo_owner(user_id, repo_id):
method seafile_set_repo_owner (line 55) | def seafile_set_repo_owner(email, repo_id):
method seafile_get_repo_owner (line 60) | def seafile_get_repo_owner(repo_id):
method seafile_get_orphan_repo_list (line 65) | def seafile_get_orphan_repo_list():
method seafile_list_owned_repos (line 70) | def seafile_list_owned_repos(user_id, ret_corrupted, start, limit):
method seafile_search_repos_by_name (line 75) | def seafile_search_repos_by_name(name):
method seafile_server_repo_size (line 80) | def seafile_server_repo_size(repo_id):
method seafile_repo_set_access_property (line 85) | def seafile_repo_set_access_property(repo_id, role):
method seafile_repo_query_access_property (line 90) | def seafile_repo_query_access_property(repo_id):
method seafile_revert_on_server (line 95) | def seafile_revert_on_server(repo_id, commit_id, user_name):
method seafile_diff (line 100) | def seafile_diff():
method seafile_post_file (line 105) | def seafile_post_file(repo_id, tmp_file_path, parent_dir, filename, us...
method seafile_post_dir (line 110) | def seafile_post_dir(repo_id, parent_dir, new_dir_name, user):
method seafile_post_empty_file (line 115) | def seafile_post_empty_file(repo_id, parent_dir, filename, user):
method seafile_put_file (line 120) | def seafile_put_file(repo_id, tmp_file_path, parent_dir, filename, use...
method seafile_del_file (line 125) | def seafile_del_file(repo_id, parent_dir, filename, user):
method seafile_batch_del_files (line 130) | def seafile_batch_del_files(repo_id, filepaths, user):
method seafile_copy_file (line 135) | def seafile_copy_file(src_repo, src_dir, src_filename, dst_repo, dst_d...
method seafile_move_file (line 140) | def seafile_move_file(src_repo, src_dir, src_filename, dst_repo, dst_d...
method seafile_rename_file (line 145) | def seafile_rename_file(repo_id, parent_dir, oldname, newname, user):
method seafile_is_valid_filename (line 150) | def seafile_is_valid_filename(repo_id, filename):
method seafile_get_commit (line 155) | def seafile_get_commit(repo_id, version, commit_id):
method seafile_list_file_blocks (line 160) | def seafile_list_file_blocks(repo_id, file_id, offset, limit):
method seafile_list_dir (line 165) | def seafile_list_dir(repo_id, dir_id, offset, limit):
method list_dir_with_perm (line 170) | def list_dir_with_perm(repo_id, dir_path, dir_id, user, offset, limit):
method seafile_get_file_size (line 174) | def seafile_get_file_size(store_id, version, file_id):
method seafile_get_dir_size (line 179) | def seafile_get_dir_size(store_id, version, dir_id):
method seafile_list_dir_by_path (line 184) | def seafile_list_dir_by_path(repo_id, commit_id, path):
method seafile_get_dir_id_by_commit_and_path (line 189) | def seafile_get_dir_id_by_commit_and_path(repo_id, commit_id, path):
method seafile_get_file_id_by_path (line 194) | def seafile_get_file_id_by_path(repo_id, path):
method seafile_get_dir_id_by_path (line 199) | def seafile_get_dir_id_by_path(repo_id, path):
method seafile_get_file_id_by_commit_and_path (line 204) | def seafile_get_file_id_by_commit_and_path(repo_id, commit_id, path):
method seafile_get_dirent_by_path (line 209) | def seafile_get_dirent_by_path(repo_id, commit_id, path):
method seafile_list_file_revisions (line 214) | def seafile_list_file_revisions(repo_id, commit_id, path, limit):
method seafile_calc_files_last_modified (line 219) | def seafile_calc_files_last_modified(repo_id, parent_dir, limit):
method seafile_revert_file (line 224) | def seafile_revert_file(repo_id, commit_id, path, user):
method seafile_check_repo_blocks_missing (line 229) | def seafile_check_repo_blocks_missing(repo_id, blklist):
method seafile_revert_dir (line 234) | def seafile_revert_dir(repo_id, commit_id, path, user):
method get_deleted (line 239) | def get_deleted(repo_id, show_days, path, scan_stat, limit):
method seafile_add_share (line 244) | def seafile_add_share(repo_id, from_email, to_email, permission):
method seafile_list_share_repos (line 249) | def seafile_list_share_repos(email, query_col, start, limit):
method seafile_list_repo_shared_to (line 254) | def seafile_list_repo_shared_to(from_user, repo_id):
method share_subdir_to_user (line 259) | def share_subdir_to_user(repo_id, path, owner, share_user, permission,...
method unshare_subdir_for_user (line 263) | def unshare_subdir_for_user(repo_id, path, owner, share_user):
method update_share_subdir_perm_for_user (line 267) | def update_share_subdir_perm_for_user(repo_id, path, owner, share_user...
method get_shared_repo_by_path (line 271) | def get_shared_repo_by_path(repo_id, path, shared_to, is_org):
method seafile_list_org_share_repos (line 275) | def seafile_list_org_share_repos(org_id, email, query_col, start, limit):
method seafile_remove_share (line 280) | def seafile_remove_share(repo_id, from_email, to_email):
method set_share_permission (line 285) | def set_share_permission(repo_id, from_email, to_email, permission):
method seafile_group_share_repo (line 290) | def seafile_group_share_repo(repo_id, group_id, user_name, permisson):
method seafile_group_unshare_repo (line 295) | def seafile_group_unshare_repo(repo_id, group_id, user_name):
method seafile_get_shared_groups_by_repo (line 300) | def seafile_get_shared_groups_by_repo(repo_id):
method seafile_list_repo_shared_group (line 305) | def seafile_list_repo_shared_group(from_user, repo_id):
method get_group_shared_repo_by_path (line 310) | def get_group_shared_repo_by_path(repo_id, path, group_id, is_org):
method get_group_repos_by_user (line 314) | def get_group_repos_by_user (user):
method get_org_group_repos_by_user (line 318) | def get_org_group_repos_by_user (user, org_id):
method seafile_get_shared_users_for_subdir (line 322) | def seafile_get_shared_users_for_subdir(repo_id, path, from_user):
method seafile_get_shared_groups_for_subdir (line 327) | def seafile_get_shared_groups_for_subdir(repo_id, path, from_user):
method share_subdir_to_group (line 332) | def share_subdir_to_group(repo_id, path, owner, share_group, permissio...
method unshare_subdir_for_group (line 336) | def unshare_subdir_for_group(repo_id, path, owner, share_group):
method update_share_subdir_perm_for_group (line 340) | def update_share_subdir_perm_for_group(repo_id, path, owner, share_gro...
method seafile_get_group_repoids (line 344) | def seafile_get_group_repoids(group_id):
method seafile_get_repos_by_group (line 349) | def seafile_get_repos_by_group(group_id):
method get_group_repos_by_owner (line 354) | def get_group_repos_by_owner(user_name):
method get_group_repo_owner (line 358) | def get_group_repo_owner(repo_id):
method seafile_remove_repo_group (line 362) | def seafile_remove_repo_group(group_id, user_name):
method set_group_repo_permission (line 367) | def set_group_repo_permission(group_id, repo_id, permission):
method seafile_branch_gets (line 372) | def seafile_branch_gets(repo_id):
method seafile_get_commit_list (line 377) | def seafile_get_commit_list(repo_id, offset, limit):
method seafile_set_repo_token (line 385) | def seafile_set_repo_token(repo_id, email, token):
method seafile_get_repo_token_nonnull (line 390) | def seafile_get_repo_token_nonnull(repo_id, email):
method seafile_generate_repo_token (line 400) | def seafile_generate_repo_token(repo_id, email):
method seafile_delete_repo_token (line 405) | def seafile_delete_repo_token(repo_id, token, user):
method seafile_list_repo_tokens (line 410) | def seafile_list_repo_tokens(repo_id):
method seafile_list_repo_tokens_by_email (line 415) | def seafile_list_repo_tokens_by_email(email):
method seafile_delete_repo_tokens_by_peer_id (line 420) | def seafile_delete_repo_tokens_by_peer_id(email, user_id):
method delete_repo_tokens_by_email (line 425) | def delete_repo_tokens_by_email(email):
method seafile_get_user_quota_usage (line 430) | def seafile_get_user_quota_usage(user_id):
method seafile_get_user_share_usage (line 435) | def seafile_get_user_share_usage(user_id):
method seafile_get_org_quota_usage (line 440) | def seafile_get_org_quota_usage(org_id):
method seafile_get_org_user_quota_usage (line 445) | def seafile_get_org_user_quota_usage(org_id, user):
method set_user_quota (line 450) | def set_user_quota(user, quota):
method get_user_quota (line 454) | def get_user_quota(user):
method set_org_quota (line 458) | def set_org_quota(org_id, quota):
method get_org_quota (line 462) | def get_org_quota(org_id):
method set_org_user_quota (line 466) | def set_org_user_quota(org_id, user, quota):
method get_org_user_quota (line 470) | def get_org_user_quota(org_id, user):
method check_quota (line 474) | def check_quota(repo_id, delta):
method list_user_quota_usage (line 478) | def list_user_quota_usage():
method seafile_check_passwd (line 483) | def seafile_check_passwd(repo_id, magic):
method seafile_set_passwd (line 488) | def seafile_set_passwd(repo_id, user, passwd):
method seafile_unset_passwd (line 493) | def seafile_unset_passwd(repo_id, user):
method check_permission (line 499) | def check_permission(repo_id, user):
method check_permission_by_path (line 504) | def check_permission_by_path(repo_id, path, user):
method seafile_create_org_repo (line 509) | def seafile_create_org_repo(name, desc, user, passwd, magic, random_ke...
method seafile_get_org_id_by_repo_id (line 514) | def seafile_get_org_id_by_repo_id(repo_id):
method seafile_get_org_repo_list (line 519) | def seafile_get_org_repo_list(org_id, start, limit):
method seafile_remove_org_repo_by_org_id (line 524) | def seafile_remove_org_repo_by_org_id(org_id):
method list_org_repos_by_owner (line 529) | def list_org_repos_by_owner(org_id, user):
method get_org_repo_owner (line 533) | def get_org_repo_owner(repo_id):
method add_org_group_repo (line 538) | def add_org_group_repo(repo_id, org_id, group_id, owner, permission):
method del_org_group_repo (line 542) | def del_org_group_repo(repo_id, org_id, group_id):
method get_org_group_repoids (line 546) | def get_org_group_repoids(org_id, group_id):
method get_org_group_repo_owner (line 550) | def get_org_group_repo_owner(org_id, group_id, repo_id):
method get_org_group_repos_by_owner (line 554) | def get_org_group_repos_by_owner(org_id, user):
method get_org_groups_by_repo (line 558) | def get_org_groups_by_repo(org_id, repo_id):
method set_org_group_repo_permission (line 562) | def set_org_group_repo_permission(org_id, group_id, repo_id, permission):
method set_inner_pub_repo (line 567) | def set_inner_pub_repo(repo_id, permission):
method unset_inner_pub_repo (line 571) | def unset_inner_pub_repo(repo_id):
method list_inner_pub_repos (line 575) | def list_inner_pub_repos():
method list_inner_pub_repos_by_owner (line 579) | def list_inner_pub_repos_by_owner(user):
method count_inner_pub_repos (line 583) | def count_inner_pub_repos():
method is_inner_pub_repo (line 587) | def is_inner_pub_repo(repo_id):
method set_org_inner_pub_repo (line 592) | def set_org_inner_pub_repo(org_id, repo_id, permission):
method unset_org_inner_pub_repo (line 596) | def unset_org_inner_pub_repo(org_id, repo_id):
method list_org_inner_pub_repos (line 600) | def list_org_inner_pub_repos(org_id):
method list_org_inner_pub_repos_by_owner (line 604) | def list_org_inner_pub_repos_by_owner(org_id, user):
method set_repo_history_limit (line 608) | def set_repo_history_limit(repo_id, days):
method get_repo_history_limit (line 612) | def get_repo_history_limit(repo_id):
method set_repo_valid_since (line 616) | def set_repo_valid_since(repo_id, timestamp):
method create_virtual_repo (line 621) | def create_virtual_repo(origin_repo_id, path, repo_name, repo_desc, ow...
method get_virtual_repos_by_owner (line 625) | def get_virtual_repos_by_owner(owner):
method get_virtual_repo (line 629) | def get_virtual_repo(origin_repo, path, owner):
method get_system_default_repo_id (line 634) | def get_system_default_repo_id():
method seafile_change_repo_passwd (line 639) | def seafile_change_repo_passwd(repo_id, old_passwd, new_passwd, user):
method seafile_upgrade_repo_pwd_hash_algorithm (line 645) | def seafile_upgrade_repo_pwd_hash_algorithm (repo_id, user, passwd, pw...
method clean_up_repo_history (line 651) | def clean_up_repo_history(repo_id, keep_days):
method get_trash_repo_list (line 656) | def get_trash_repo_list(start, limit):
method del_repo_from_trash (line 660) | def del_repo_from_trash(repo_id):
method restore_repo_from_trash (line 664) | def restore_repo_from_trash(repo_id):
method get_trash_repos_by_owner (line 668) | def get_trash_repos_by_owner(owner):
method empty_repo_trash (line 672) | def empty_repo_trash():
method empty_repo_trash_by_owner (line 676) | def empty_repo_trash_by_owner(owner):
method empty_repo_trash_by_owner (line 680) | def empty_repo_trash_by_owner(owner):
method generate_magic_and_random_key (line 684) | def generate_magic_and_random_key(enc_version, repo_id, password):
method get_total_file_number (line 688) | def get_total_file_number():
method get_total_storage (line 692) | def get_total_storage():
method get_file_count_info_by_path (line 696) | def get_file_count_info_by_path(repo_id, path):
method get_trash_repo_owner (line 700) | def get_trash_repo_owner(repo_id):
method seafile_get_upload_tmp_file_offset (line 704) | def seafile_get_upload_tmp_file_offset(repo_id, file_path):
method seafile_mkdir_with_parents (line 709) | def seafile_mkdir_with_parents (repo_id, parent_dir, relative_path, us...
method get_server_config_int (line 714) | def get_server_config_int (group, key):
method set_server_config_int (line 718) | def set_server_config_int (group, key, value):
method get_server_config_int64 (line 722) | def get_server_config_int64 (group, key):
method set_server_config_int64 (line 726) | def set_server_config_int64 (group, key, value):
method get_server_config_string (line 730) | def get_server_config_string (group, key):
method set_server_config_string (line 734) | def set_server_config_string (group, key, value):
method get_server_config_boolean (line 738) | def get_server_config_boolean (group, key):
method set_server_config_boolean (line 742) | def set_server_config_boolean (group, key, value):
method repo_has_been_shared (line 746) | def repo_has_been_shared (repo_id, including_groups):
method get_shared_users_by_repo (line 750) | def get_shared_users_by_repo (repo_id):
method org_get_shared_users_by_repo (line 754) | def org_get_shared_users_by_repo (org_id, repo_id):
method convert_repo_path (line 758) | def convert_repo_path(repo_id, path, user, is_org):
method set_repo_status (line 763) | def set_repo_status(repo_id, status):
method get_repo_status (line 767) | def get_repo_status(repo_id):
method seafile_web_get_access_token (line 772) | def seafile_web_get_access_token(repo_id, obj_id, op, username, use_on...
method seafile_web_query_access_token (line 777) | def seafile_web_query_access_token(token):
method seafile_query_zip_progress (line 782) | def seafile_query_zip_progress(token):
method cancel_zip_task (line 787) | def cancel_zip_task(token):
method seafile_gc (line 792) | def seafile_gc():
method seafile_gc_get_progress (line 797) | def seafile_gc_get_progress():
method seafile_is_passwd_set (line 803) | def seafile_is_passwd_set(repo_id, user):
method seafile_get_decrypt_key (line 808) | def seafile_get_decrypt_key(repo_id, user):
method get_copy_task (line 815) | def get_copy_task(task_id):
method cancel_copy_task (line 819) | def cancel_copy_task(task_id):
method publish_event (line 824) | def publish_event(channel, content):
method pop_event (line 828) | def pop_event(channel):
method search_files (line 832) | def search_files(self, repo_id, search_str):
method search_files_by_path (line 836) | def search_files_by_path(self, repo_id, path, search_str):
method add_emailuser (line 841) | def add_emailuser(self, email, passwd, is_staff, is_active):
method remove_emailuser (line 845) | def remove_emailuser(self, source, email):
method validate_emailuser (line 849) | def validate_emailuser(self, email, passwd):
method get_emailuser (line 853) | def get_emailuser(self, email):
method get_emailuser_with_import (line 857) | def get_emailuser_with_import(self, email):
method get_emailuser_by_id (line 861) | def get_emailuser_by_id(self, user_id):
method get_emailusers (line 865) | def get_emailusers(self, source, start, limit, status):
method search_emailusers (line 869) | def search_emailusers(self, source, email_patt, start, limit):
method count_emailusers (line 873) | def count_emailusers(self, source):
method count_inactive_emailusers (line 877) | def count_inactive_emailusers(self, source):
method filter_emailusers_by_emails (line 881) | def filter_emailusers_by_emails(self):
method update_emailuser (line 885) | def update_emailuser(self, source, user_id, password, is_staff, is_act...
method update_role_emailuser (line 889) | def update_role_emailuser(self, email, role):
method get_superusers (line 893) | def get_superusers(self):
method get_emailusers_in_list (line 897) | def get_emailusers_in_list(self, source, user_list):
method update_emailuser_id (line 901) | def update_emailuser_id (self, old_email, new_email):
method create_group (line 906) | def create_group(self, group_name, user_name, gtype, parent_group_id):
method create_org_group (line 910) | def create_org_group(self, org_id, group_name, user_name, parent_group...
method remove_group (line 914) | def remove_group(self, group_id):
method group_add_member (line 918) | def group_add_member(self, group_id, user_name, member_name):
method group_remove_member (line 922) | def group_remove_member(self, group_id, user_name, member_name):
method group_set_admin (line 926) | def group_set_admin(self, group_id, member_name):
method group_unset_admin (line 930) | def group_unset_admin(self, group_id, member_name):
method set_group_name (line 934) | def set_group_name(self, group_id, group_name):
method quit_group (line 938) | def quit_group(self, group_id, user_name):
method get_groups (line 942) | def get_groups(self, user_name, return_ancestors):
method list_all_departments (line 946) | def list_all_departments(self):
method get_all_groups (line 950) | def get_all_groups(self, start, limit, source):
method get_ancestor_groups (line 954) | def get_ancestor_groups(self, group_id):
method get_top_groups (line 958) | def get_top_groups(self, including_org):
method get_child_groups (line 962) | def get_child_groups(self, group_id):
method get_descendants_groups (line 966) | def get_descendants_groups(self, group_id):
method get_group (line 970) | def get_group(self, group_id):
method get_group_members (line 974) | def get_group_members(self, group_id):
method get_members_with_prefix (line 978) | def get_members_with_prefix(self, group_id, prefix):
method check_group_staff (line 982) | def check_group_staff(self, group_id, username, in_structure):
method remove_group_user (line 986) | def remove_group_user(self, username):
method is_group_user (line 990) | def is_group_user(self, group_id, user, in_structure):
method set_group_creator (line 994) | def set_group_creator(self, group_id, user_name):
method search_groups (line 998) | def search_groups(self, group_patt, start, limit):
method search_group_members (line 1002) | def search_group_members(self, group_id, pattern):
method get_groups_members (line 1006) | def get_groups_members(self, group_ids):
method create_org (line 1010) | def create_org(self, org_name, url_prefix, creator):
method remove_org (line 1014) | def remove_org(self, org_id):
method get_all_orgs (line 1018) | def get_all_orgs(self, start, limit):
method count_orgs (line 1022) | def count_orgs(self):
method get_org_by_url_prefix (line 1026) | def get_org_by_url_prefix(self, url_prefix):
method get_org_by_id (line 1030) | def get_org_by_id(self, org_id):
method add_org_user (line 1034) | def add_org_user(self, org_id, email, is_staff):
method remove_org_user (line 1038) | def remove_org_user(self, org_id, email):
method get_orgs_by_user (line 1042) | def get_orgs_by_user(self, email):
method get_org_emailusers (line 1046) | def get_org_emailusers(self, url_prefix, start, limit):
method add_org_group (line 1050) | def add_org_group(self, org_id, group_id):
method remove_org_group (line 1054) | def remove_org_group(self, org_id, group_id):
method is_org_group (line 1058) | def is_org_group(self, group_id):
method get_org_id_by_group (line 1062) | def get_org_id_by_group(self, group_id):
method get_org_groups (line 1066) | def get_org_groups(self, org_id, start, limit):
method get_org_groups_by_user (line 1070) | def get_org_groups_by_user (self, user, org_id):
method get_org_top_groups (line 1074) | def get_org_top_groups(self, org_id):
method org_user_exists (line 1078) | def org_user_exists(self, org_id, email):
method is_org_staff (line 1082) | def is_org_staff(self, org_id, user):
method set_org_staff (line 1086) | def set_org_staff(self, org_id, user):
method unset_org_staff (line 1090) | def unset_org_staff(self, org_id, user):
method set_org_name (line 1094) | def set_org_name(self, org_id, org_name):
method get_primary_id (line 1098) | def get_primary_id(self, email):
FILE: python/seaserv/api.py
class SeafileAPI (line 19) | class SeafileAPI(object):
method __init__ (line 21) | def __init__(self):
method get_fileserver_access_token (line 26) | def get_fileserver_access_token(self, repo_id, obj_id, op, username, u...
method query_fileserver_access_token (line 39) | def query_fileserver_access_token(self, token):
method query_zip_progress (line 48) | def query_zip_progress(self, token):
method cancel_zip_task (line 55) | def cancel_zip_task(self, token):
method is_password_set (line 60) | def is_password_set(self, repo_id, username):
method get_decrypt_key (line 66) | def get_decrypt_key(self, repo_id, username):
method change_repo_passwd (line 72) | def change_repo_passwd(self, repo_id, old_passwd, new_passwd, user):
method upgrade_repo_pwd_hash_algorithm (line 76) | def upgrade_repo_pwd_hash_algorithm (self, repo_id, user, passwd, pwd_...
method check_passwd (line 79) | def check_passwd(self, repo_id, magic):
method set_passwd (line 82) | def set_passwd(self, repo_id, user, passwd):
method unset_passwd (line 85) | def unset_passwd(self, repo_id, user):
method generate_magic_and_random_key (line 88) | def generate_magic_and_random_key(self, enc_version, repo_id, password):
method create_repo (line 93) | def create_repo(self, name, desc, username, passwd=None, enc_version=2...
method create_enc_repo (line 96) | def create_enc_repo(self, repo_id, name, desc, username, magic, random...
method get_repos_by_id_prefix (line 99) | def get_repos_by_id_prefix(self, id_prefix, start=-1, limit=-1):
method get_repo (line 105) | def get_repo(self, repo_id):
method remove_repo (line 111) | def remove_repo(self, repo_id):
method get_repo_list (line 114) | def get_repo_list(self, start, limit, order_by=None, ret_virt_repo=Fal...
method count_repos (line 120) | def count_repos(self):
method edit_repo (line 123) | def edit_repo(self, repo_id, name, description, username):
method is_repo_owner (line 126) | def is_repo_owner(self, username, repo_id):
method set_repo_owner (line 132) | def set_repo_owner(self, email, repo_id):
method get_repo_owner (line 135) | def get_repo_owner(self, repo_id):
method get_owned_repo_list (line 141) | def get_owned_repo_list(self, username, ret_corrupted=False, start=-1,...
method search_repos_by_name (line 149) | def search_repos_by_name(self, name):
method get_orphan_repo_list (line 152) | def get_orphan_repo_list(self):
method get_repo_size (line 155) | def get_repo_size(self, repo_id):
method revert_repo (line 158) | def revert_repo(self, repo_id, commit_id, username):
method diff_commits (line 161) | def diff_commits(self, repo_id, old_commit, new_commit, fold_dir_diff ...
method get_commit_list (line 167) | def get_commit_list(self, repo_id, offset, limit):
method get_commit (line 173) | def get_commit(self, repo_id, repo_version, cmt_id):
method get_system_default_repo_id (line 181) | def get_system_default_repo_id (self):
method get_org_id_by_repo_id (line 184) | def get_org_id_by_repo_id (self, repo_id):
method set_repo_status (line 187) | def set_repo_status (self, repo_id, status):
method get_repo_status (line 190) | def get_repo_status (self, repo_id):
method is_valid_filename (line 195) | def is_valid_filename(self, repo_id, filename):
method get_file_size (line 201) | def get_file_size(self, store_id, version, file_id):
method get_dir_size (line 204) | def get_dir_size(self, store_id, version, dir_id):
method get_file_id_by_path (line 211) | def get_file_id_by_path(self, repo_id, path):
method get_file_id_by_commit_and_path (line 217) | def get_file_id_by_commit_and_path(self, repo_id, commit_id, path):
method get_dirent_by_path (line 222) | def get_dirent_by_path(self, repo_id, path):
method list_file_by_file_id (line 228) | def list_file_by_file_id(self, repo_id, file_id, offset=-1, limit=-1):
method list_blocks_by_file_id (line 232) | def list_blocks_by_file_id(self, repo_id, file_id, offset=-1, limit=-1):
method get_dir_id_by_path (line 239) | def get_dir_id_by_path(self, repo_id, path):
method list_dir_by_dir_id (line 242) | def list_dir_by_dir_id(self, repo_id, dir_id, offset=-1, limit=-1):
method list_dir_by_path (line 250) | def list_dir_by_path(self, repo_id, path, offset=-1, limit=-1):
method list_dir_by_commit_and_path (line 256) | def list_dir_by_commit_and_path(self, repo_id,
method get_dir_id_by_commit_and_path (line 263) | def get_dir_id_by_commit_and_path(self, repo_id, commit_id, path):
method list_dir_with_perm (line 266) | def list_dir_with_perm(self, repo_id, dir_path, dir_id, user, offset=-...
method mkdir_with_parents (line 269) | def mkdir_with_parents (self, repo_id, parent_dir, relative_path, user...
method get_file_count_info_by_path (line 272) | def get_file_count_info_by_path(self, repo_id, path):
method get_total_storage (line 275) | def get_total_storage (self):
method get_total_file_number (line 278) | def get_total_file_number (self):
method post_file (line 283) | def post_file(self, repo_id, tmp_file_path, parent_dir, filename, user...
method post_empty_file (line 288) | def post_empty_file(self, repo_id, parent_dir, filename, username):
method put_file (line 292) | def put_file(self, repo_id, tmp_file_path, parent_dir, filename,
method del_file (line 304) | def del_file(self, repo_id, parent_dir, filename, username):
method batch_del_files (line 307) | def batch_del_files(self, repo_id, filepaths, username):
method copy_file (line 315) | def copy_file(self, src_repo, src_dir, src_filename, dst_repo,
method move_file (line 321) | def move_file(self, src_repo, src_dir, src_filename, dst_repo, dst_dir,
method get_copy_task (line 327) | def get_copy_task(self, task_id):
method cancel_copy_task (line 330) | def cancel_copy_task(self, task_id):
method rename_file (line 333) | def rename_file(self, repo_id, parent_dir, oldname, newname, username):
method post_dir (line 337) | def post_dir(self, repo_id, parent_dir, dirname, username):
method revert_file (line 341) | def revert_file(self, repo_id, commit_id, path, username):
method revert_dir (line 344) | def revert_dir(self, repo_id, commit_id, path, username):
method get_deleted (line 347) | def get_deleted(self, repo_id, show_days, path='/', scan_stat=None, li...
method get_file_revisions (line 367) | def get_file_revisions(self, repo_id, commit_id, path, limit):
method get_files_last_modified (line 386) | def get_files_last_modified(self, repo_id, parent_dir, limit):
method get_repo_history_limit (line 394) | def get_repo_history_limit(self, repo_id):
method set_repo_history_limit (line 400) | def set_repo_history_limit(self, repo_id, days):
method set_repo_valid_since (line 406) | def set_repo_valid_since(self, repo_id, timestamp):
method check_repo_blocks_missing (line 409) | def check_repo_blocks_missing(self, repo_id, blklist):
method get_upload_tmp_file_offset (line 412) | def get_upload_tmp_file_offset (self, repo_id, file_path):
method check_file_lock (line 416) | def check_file_lock(self, repo_id, path, user):
method share_repo (line 423) | def share_repo(self, repo_id, from_username, to_username, permission):
method remove_share (line 427) | def remove_share(self, repo_id, from_username, to_username):
method set_share_permission (line 431) | def set_share_permission(self, repo_id, from_username, to_username, pe...
method share_subdir_to_user (line 435) | def share_subdir_to_user(self, repo_id, path, owner, share_user, permi...
method unshare_subdir_for_user (line 439) | def unshare_subdir_for_user(self, repo_id, path, owner, share_user):
method update_share_subdir_perm_for_user (line 443) | def update_share_subdir_perm_for_user(self, repo_id, path, owner,
method get_shared_repo_by_path (line 448) | def get_shared_repo_by_path(self, repo_id, path, shared_to, is_org=Fal...
method get_share_out_repo_list (line 455) | def get_share_out_repo_list(self, username, start, limit):
method get_share_in_repo_list (line 463) | def get_share_in_repo_list(self, username, start, limit):
method list_repo_shared_to (line 470) | def list_repo_shared_to(self, from_user, repo_id):
method repo_has_been_shared (line 477) | def repo_has_been_shared(self, repo_id, including_groups=False):
method group_share_repo (line 481) | def group_share_repo(self, repo_id, group_id, username, permission):
method set_group_repo (line 486) | def set_group_repo(self, repo_id, group_id, username, permission):
method group_unshare_repo (line 490) | def group_unshare_repo(self, repo_id, group_id, username):
method unset_group_repo (line 494) | def unset_group_repo(self, repo_id, group_id, username):
method get_shared_group_ids_by_repo (line 497) | def get_shared_group_ids_by_repo(self, repo_id):
method list_repo_shared_group (line 510) | def list_repo_shared_group(self, from_user, repo_id):
method get_group_shared_repo_by_path (line 514) | def get_group_shared_repo_by_path (self, repo_id, path, group_id, is_o...
method get_group_repos_by_user (line 521) | def get_group_repos_by_user (self, user):
method get_org_group_repos_by_user (line 527) | def get_org_group_repos_by_user (self, user, org_id):
method list_repo_shared_group_by_user (line 530) | def list_repo_shared_group_by_user(self, from_user, repo_id):
method share_subdir_to_group (line 536) | def share_subdir_to_group(self, repo_id, path, owner, share_group, per...
method unshare_subdir_for_group (line 540) | def unshare_subdir_for_group(self, repo_id, path, owner, share_group):
method update_share_subdir_perm_for_group (line 544) | def update_share_subdir_perm_for_group(self, repo_id, path, owner,
method get_group_repoids (line 549) | def get_group_repoids(self, group_id):
method get_group_repo_list (line 563) | def get_group_repo_list(self, group_id):
method get_repos_by_group (line 573) | def get_repos_by_group(self, group_id):
method get_group_repos_by_owner (line 579) | def get_group_repos_by_owner(self, username):
method remove_group_repos_by_owner (line 586) | def remove_group_repos_by_owner(self, group_id, username):
method remove_group_repos (line 592) | def remove_group_repos(self, group_id):
method set_group_repo_permission (line 599) | def set_group_repo_permission(self, group_id, repo_id, permission):
method get_shared_users_for_subdir (line 603) | def get_shared_users_for_subdir(self, repo_id, path, from_user):
method get_shared_groups_for_subdir (line 610) | def get_shared_groups_for_subdir(self, repo_id, path, from_user):
method get_shared_users_by_repo (line 617) | def get_shared_users_by_repo(self, repo_id):
method add_inner_pub_repo (line 645) | def add_inner_pub_repo(self, repo_id, permission):
method remove_inner_pub_repo (line 648) | def remove_inner_pub_repo(self, repo_id):
method get_inner_pub_repo_list (line 651) | def get_inner_pub_repo_list(self):
method list_inner_pub_repos_by_owner (line 657) | def list_inner_pub_repos_by_owner(self, repo_owner):
method count_inner_pub_repos (line 663) | def count_inner_pub_repos(self):
method is_inner_pub_repo (line 666) | def is_inner_pub_repo(self, repo_id):
method check_permission (line 670) | def check_permission(self, repo_id, user):
method check_permission_by_path (line 678) | def check_permission_by_path(self, repo_id, path, user):
method is_repo_syncable (line 687) | def is_repo_syncable(self, repo_id, user, repo_perm):
method is_dir_downloadable (line 693) | def is_dir_downloadable(self, repo_id, dir_path, user, repo_perm):
method generate_repo_token (line 703) | def generate_repo_token(self, repo_id, username):
method delete_repo_token (line 708) | def delete_repo_token(self, repo_id, token, user):
method list_repo_tokens (line 711) | def list_repo_tokens(self, repo_id):
method list_repo_tokens_by_email (line 717) | def list_repo_tokens_by_email(self, username):
method delete_repo_tokens_by_peer_id (line 720) | def delete_repo_tokens_by_peer_id(self, email, peer_id):
method delete_repo_tokens_by_email (line 723) | def delete_repo_tokens_by_email(self, email):
method get_user_self_usage (line 727) | def get_user_self_usage(self, username):
method get_user_share_usage (line 731) | def get_user_share_usage(self, username):
method get_user_quota (line 735) | def get_user_quota(self, username):
method set_user_quota (line 741) | def set_user_quota(self, username, quota):
method get_user_share_quota (line 744) | def get_user_share_quota(self, username):
method set_user_share_quota (line 747) | def set_user_share_quota(self, username, quota):
method check_quota (line 750) | def check_quota(self, repo_id, delta=0):
method list_user_quota_usage (line 753) | def list_user_quota_usage(self):
method create_virtual_repo (line 757) | def create_virtual_repo(self, origin_repo_id, path, repo_name, repo_de...
method get_virtual_repos_by_owner (line 765) | def get_virtual_repos_by_owner(self, owner):
method get_virtual_repo (line 768) | def get_virtual_repo(self, origin_repo, path, owner):
method clean_up_repo_history (line 773) | def clean_up_repo_history(self, repo_id, keep_days):
method get_trash_repo_list (line 777) | def get_trash_repo_list(self, start, limit):
method del_repo_from_trash (line 780) | def del_repo_from_trash(self, repo_id):
method restore_repo_from_trash (line 783) | def restore_repo_from_trash(self, repo_id):
method get_trash_repos_by_owner (line 786) | def get_trash_repos_by_owner(self, owner):
method get_trash_repo_owner (line 789) | def get_trash_repo_owner (self, repo_id):
method empty_repo_trash (line 792) | def empty_repo_trash(self):
method empty_repo_trash_by_owner (line 795) | def empty_repo_trash_by_owner(self, owner):
method get_server_config_int (line 799) | def get_server_config_int (self, group, key):
method set_server_config_int (line 802) | def set_server_config_int (self, group, key, value):
method get_server_config_int64 (line 805) | def get_server_config_int64 (self, group, key):
method set_server_config_int64 (line 808) | def set_server_config_int64 (self, group, key, value):
method get_server_config_string (line 811) | def get_server_config_string (self, group, key):
method set_server_config_string (line 814) | def set_server_config_string (self, group, key, value):
method get_server_config_boolean (line 817) | def get_server_config_boolean (self, group, key):
method set_server_config_boolean (line 820) | def set_server_config_boolean (self, group, key, value):
method del_org_group_repo (line 824) | def del_org_group_repo(self, repo_id, org_id, group_id):
method org_get_shared_users_by_repo (line 827) | def org_get_shared_users_by_repo(self, org_id, repo_id):
method list_org_inner_pub_repos (line 854) | def list_org_inner_pub_repos(self, org_id):
method convert_repo_path (line 857) | def convert_repo_path(self, repo_id, path, user, is_org=False):
method publish_event (line 860) | def publish_event(self, channel, content):
method pop_event (line 863) | def pop_event(self, channel):
method search_files (line 866) | def search_files(self, repo_id, search_str):
method search_files_by_path (line 869) | def search_files_by_path (self, repo_id, path, search_str):
class CcnetAPI (line 874) | class CcnetAPI(object):
method __init__ (line 876) | def __init__(self):
method add_emailuser (line 880) | def add_emailuser(self, email, passwd, is_staff, is_active):
method remove_emailuser (line 883) | def remove_emailuser(self, source, email):
method validate_emailuser (line 891) | def validate_emailuser(self, email, passwd):
method get_emailuser (line 898) | def get_emailuser(self, email):
method get_emailuser_with_import (line 909) | def get_emailuser_with_import(self, email):
method get_emailuser_by_id (line 916) | def get_emailuser_by_id(self, user_id):
method get_emailusers (line 922) | def get_emailusers(self, source, start, limit, is_active=None):
method search_emailusers (line 943) | def search_emailusers(self, source, email_patt, start, limit):
method search_groups (line 951) | def search_groups(self, group_patt, start, limit):
method search_group_members (line 957) | def search_group_members(self, group_id, pattern):
method get_top_groups (line 960) | def get_top_groups(self, including_org=False):
method get_child_groups (line 963) | def get_child_groups(self, group_id):
method get_descendants_groups (line 966) | def get_descendants_groups(self, group_id):
method get_ancestor_groups (line 969) | def get_ancestor_groups(self, group_id):
method count_emailusers (line 972) | def count_emailusers(self, source):
method count_inactive_emailusers (line 979) | def count_inactive_emailusers(self, source):
method update_emailuser (line 986) | def update_emailuser(self, source, user_id, password, is_staff, is_act...
method update_role_emailuser (line 997) | def update_role_emailuser(self, email, role, is_manual_set=True):
method get_superusers (line 1000) | def get_superusers(self):
method get_emailusers_in_list (line 1006) | def get_emailusers_in_list(self, source, user_list):
method update_emailuser_id (line 1013) | def update_emailuser_id (self, old_email, new_email):
method create_group (line 1017) | def create_group(self, group_name, user_name, gtype=None, parent_group...
method create_org_group (line 1023) | def create_org_group(self, org_id, group_name, user_name, parent_group...
method remove_group (line 1026) | def remove_group(self, group_id):
method group_add_member (line 1032) | def group_add_member(self, group_id, user_name, member_name):
method group_remove_member (line 1038) | def group_remove_member(self, group_id, user_name, member_name):
method group_set_admin (line 1044) | def group_set_admin(self, group_id, member_name):
method group_unset_admin (line 1050) | def group_unset_admin(self, group_id, member_name):
method set_group_name (line 1056) | def set_group_name(self, group_id, group_name):
method quit_group (line 1059) | def quit_group(self, group_id, user_name):
method get_groups (line 1062) | def get_groups(self, user_name, return_ancestors=False):
method get_all_groups (line 1069) | def get_all_groups(self, start, limit, source=None):
method get_group (line 1075) | def get_group(self, group_id):
method get_group_members (line 1078) | def get_group_members(self, group_id, start=-1, limit=-1):
method get_members_with_prefix (line 1084) | def get_members_with_prefix (self, group_id, prefix=None):
method check_group_staff (line 1090) | def check_group_staff(self, group_id, username, in_structure=False):
method remove_group_user (line 1096) | def remove_group_user(self, username):
method is_group_user (line 1099) | def is_group_user(self, group_id, user, in_structure=True):
method set_group_creator (line 1106) | def set_group_creator(self, group_id, user_name):
method create_org (line 1110) | def create_org(self, org_name, url_prefix, creator):
method remove_org (line 1113) | def remove_org(self, org_id):
method get_all_orgs (line 1116) | def get_all_orgs(self, start, limit):
method count_orgs (line 1122) | def count_orgs(self):
method get_org_by_url_prefix (line 1125) | def get_org_by_url_prefix(self, url_prefix):
method get_org_by_id (line 1131) | def get_org_by_id(self, org_id):
method add_org_user (line 1134) | def add_org_user(self, org_id, email, is_staff):
method remove_org_user (line 1137) | def remove_org_user(self, org_id, email):
method get_orgs_by_user (line 1140) | def get_orgs_by_user(self, email):
method get_org_emailusers (line 1143) | def get_org_emailusers(self, url_prefix, start, limit):
method add_org_group (line 1149) | def add_org_group(self, org_id, group_id):
method remove_org_group (line 1152) | def remove_org_group(self, org_id, group_id):
method is_org_group (line 1155) | def is_org_group(self, group_id):
method get_org_id_by_group (line 1161) | def get_org_id_by_group(self, group_id):
method get_org_groups (line 1164) | def get_org_groups(self, org_id, start, limit):
method get_org_top_groups (line 1170) | def get_org_top_groups(self, org_id):
method org_user_exists (line 1173) | def org_user_exists(self, org_id, email):
method is_org_staff (line 1179) | def is_org_staff(self, org_id, user):
method set_org_staff (line 1185) | def set_org_staff(self, org_id, user):
method unset_org_staff (line 1188) | def unset_org_staff(self, org_id, user):
method set_org_name (line 1191) | def set_org_name(self, org_id, org_name):
method get_primary_id (line 1194) | def get_primary_id (self, email):
method get_groups_members (line 1197) | def get_groups_members(self, group_ids):
FILE: python/seaserv/service.py
function _load_path_from_env (line 20) | def _load_path_from_env(key, check=True):
function _load_data_dir (line 32) | def _load_data_dir():
function get_fileserver_option (line 55) | def get_fileserver_option(key, default):
function get_emailusers (line 100) | def get_emailusers(source, start, limit, is_active=None):
function count_emailusers (line 110) | def count_emailusers():
function get_emailuser_with_import (line 117) | def get_emailuser_with_import(email):
function get_group (line 121) | def get_group(group_id):
function get_personal_groups (line 129) | def get_personal_groups(start, limit):
function get_personal_groups_by_user (line 136) | def get_personal_groups_by_user(email):
function is_group_user (line 145) | def is_group_user(group_id, user):
function check_group_staff (line 152) | def check_group_staff(group_id, username):
function remove_group_user (line 163) | def remove_group_user(user):
function get_group_members (line 169) | def get_group_members(group_id, start=-1, limit=-1):
function is_org_group (line 178) | def is_org_group(group_id):
function get_org_id_by_group (line 185) | def get_org_id_by_group(group_id):
function get_org_groups (line 192) | def get_org_groups(org_id, start, limit):
function get_org_groups_by_user (line 199) | def get_org_groups_by_user(org_id, user):
function create_org (line 211) | def create_org(org_name, url_prefix, username):
function get_org_by_url_prefix (line 214) | def get_org_by_url_prefix(url_prefix):
function get_org_by_id (line 222) | def get_org_by_id(org_id):
function add_org_user (line 231) | def add_org_user(org_id, email, is_staff):
function remove_org_user (line 237) | def remove_org_user(org_id, email):
function org_user_exists (line 243) | def org_user_exists(org_id, user):
function get_org_users_by_url_prefix (line 250) | def get_org_users_by_url_prefix(url_prefix, start, limit):
function get_orgs_by_user (line 260) | def get_orgs_by_user(user):
function is_org_staff (line 268) | def is_org_staff(org_id, user):
function get_user_current_org (line 278) | def get_user_current_org(user, url_prefix):
function send_command (line 285) | def send_command(command):
function send_message (line 292) | def send_message(msg_type, content):
function get_binding_peerids (line 297) | def get_binding_peerids(email):
function get_repos (line 317) | def get_repos():
function get_repo (line 324) | def get_repo(repo_id):
function edit_repo (line 327) | def edit_repo(repo_id, name, desc, user):
function create_repo (line 334) | def create_repo(name, desc, user, passwd):
function remove_repo (line 345) | def remove_repo(repo_id):
function list_personal_repos_by_owner (line 356) | def list_personal_repos_by_owner(owner):
function get_repo_token_nonnull (line 366) | def get_repo_token_nonnull(repo_id, username):
function get_repo_owner (line 369) | def get_repo_owner(repo_id):
function is_repo_owner (line 379) | def is_repo_owner(user, repo_id):
function server_repo_size (line 389) | def server_repo_size(repo_id):
function create_org_repo (line 397) | def create_org_repo(repo_name, repo_desc, user, passwd, org_id):
function is_org_repo (line 409) | def is_org_repo(repo_id):
function list_org_repos_by_owner (line 413) | def list_org_repos_by_owner(org_id, user):
function get_org_repos (line 420) | def get_org_repos(org_id, start, limit):
function get_org_id_by_repo_id (line 435) | def get_org_id_by_repo_id(repo_id):
function is_org_repo_owner (line 445) | def is_org_repo_owner(org_id, repo_id, user):
function get_org_repo_owner (line 456) | def get_org_repo_owner(repo_id):
function get_commit (line 467) | def get_commit(repo_id, repo_version, cmt_id):
function get_commits (line 475) | def get_commits(repo_id, offset, limit):
function get_branches (line 484) | def get_branches(repo_id):
function get_group_repos_by_owner (line 489) | def get_group_repos_by_owner(user):
function get_shared_groups_by_repo (line 499) | def get_shared_groups_by_repo(repo_id):
function conv_repoids_to_list (line 516) | def conv_repoids_to_list(repo_ids):
function get_group_repoids (line 530) | def get_group_repoids(group_id):
function get_group_repos (line 539) | def get_group_repos(group_id, user):
function del_org_group_repo (line 563) | def del_org_group_repo(repo_id, org_id, group_id):
function get_org_group_repoids (line 566) | def get_org_group_repoids(org_id, group_id):
function get_org_group_repos (line 574) | def get_org_group_repos(org_id, group_id, user):
function get_org_groups_by_repo (line 601) | def get_org_groups_by_repo(org_id, repo_id):
function list_inner_pub_repos_by_owner (line 620) | def list_inner_pub_repos_by_owner(user):
function list_inner_pub_repos (line 630) | def list_inner_pub_repos(username):
function count_inner_pub_repos (line 645) | def count_inner_pub_repos():
function is_inner_pub_repo (line 652) | def is_inner_pub_repo(repo_id):
function unset_inner_pub_repo (line 664) | def unset_inner_pub_repo(repo_id):
function list_org_inner_pub_repos (line 668) | def list_org_inner_pub_repos(org_id, username, start=None, limit=None):
function check_permission (line 685) | def check_permission(repo_id, user):
function is_personal_repo (line 696) | def is_personal_repo(repo_id):
function list_share_repos (line 707) | def list_share_repos(user, share_type, start, limit):
function remove_share (line 715) | def remove_share(repo_id, from_user, to_user):
function unshare_group_repo (line 718) | def unshare_group_repo(repo_id, group_id, from_user):
function list_personal_shared_repos (line 722) | def list_personal_shared_repos(user, user_type, start, limit):
function list_org_shared_repos (line 735) | def list_org_shared_repos(org_id, user, user_type, start, limit):
function list_dir_by_path (line 755) | def list_dir_by_path(repo_id, commit_id, path):
function post_empty_file (line 763) | def post_empty_file(repo_id, parent_dir, file_name, user):
function del_file (line 775) | def del_file(repo_id, parent_dir, file_name, user):
function is_valid_filename (line 788) | def is_valid_filename(file_or_dir):
function get_file_size (line 799) | def get_file_size(store_id, version, file_id):
function get_file_id_by_path (line 806) | def get_file_id_by_path(repo_id, path):
function get_related_users_by_repo (line 813) | def get_related_users_by_repo(repo_id):
function get_related_users_by_org_repo (line 842) | def get_related_users_by_org_repo(org_id, repo_id):
function check_quota (line 872) | def check_quota(repo_id, delta=0):
function get_user_quota (line 880) | def get_user_quota(user):
function get_user_quota_usage (line 888) | def get_user_quota_usage(user):
function get_user_share_usage (line 896) | def get_user_share_usage(user):
function web_get_access_token (line 905) | def web_get_access_token(repo_id, obj_id, op, username, use_onetime=1):
function unset_repo_passwd (line 913) | def unset_repo_passwd(repo_id, user):
function is_passwd_set (line 926) | def is_passwd_set(repo_id, user):
function get_repo_history_limit (line 934) | def get_repo_history_limit(repo_id):
function set_repo_history_limit (line 941) | def set_repo_history_limit(repo_id, days):
FILE: scripts/sql/mysql/ccnet.sql
type Binding (line 1) | CREATE TABLE IF NOT EXISTS Binding (
type EmailUser (line 9) | CREATE TABLE IF NOT EXISTS EmailUser (
type `Group` (line 24) | CREATE TABLE IF NOT EXISTS `Group` (
type GroupDNPair (line 33) | CREATE TABLE IF NOT EXISTS GroupDNPair (
type GroupStructure (line 39) | CREATE TABLE IF NOT EXISTS GroupStructure (
type `GroupUser` (line 46) | CREATE TABLE IF NOT EXISTS `GroupUser` (
type LDAPConfig (line 55) | CREATE TABLE IF NOT EXISTS LDAPConfig (
type LDAPUsers (line 63) | CREATE TABLE IF NOT EXISTS LDAPUsers (
type OrgGroup (line 75) | CREATE TABLE IF NOT EXISTS OrgGroup (
type OrgUser (line 83) | CREATE TABLE IF NOT EXISTS OrgUser (
type Organization (line 92) | CREATE TABLE IF NOT EXISTS Organization (
type UserRole (line 101) | CREATE TABLE IF NOT EXISTS UserRole (
type OrgFileExtWhiteList (line 109) | CREATE TABLE IF NOT EXISTS OrgFileExtWhiteList (
FILE: scripts/sql/mysql/seafile.sql
type Branch (line 1) | CREATE TABLE IF NOT EXISTS Branch (
type FileLockTimestamp (line 9) | CREATE TABLE IF NOT EXISTS FileLockTimestamp (
type FileLocks (line 16) | CREATE TABLE IF NOT EXISTS FileLocks (
type FolderGroupPerm (line 26) | CREATE TABLE IF NOT EXISTS FolderGroupPerm (
type FolderPermTimestamp (line 35) | CREATE TABLE IF NOT EXISTS FolderPermTimestamp (
type FolderUserPerm (line 42) | CREATE TABLE IF NOT EXISTS FolderUserPerm (
type GCID (line 51) | CREATE TABLE IF NOT EXISTS GCID (
type GarbageRepos (line 58) | CREATE TABLE IF NOT EXISTS GarbageRepos (
type InnerPubRepo (line 64) | CREATE TABLE IF NOT EXISTS InnerPubRepo (
type LastGCID (line 71) | CREATE TABLE IF NOT EXISTS LastGCID (
type OrgGroupRepo (line 79) | CREATE TABLE IF NOT EXISTS OrgGroupRepo (
type OrgInnerPubRepo (line 90) | CREATE TABLE IF NOT EXISTS OrgInnerPubRepo (
type OrgQuota (line 98) | CREATE TABLE IF NOT EXISTS OrgQuota (
type OrgRepo (line 105) | CREATE TABLE IF NOT EXISTS OrgRepo (
type OrgSharedRepo (line 116) | CREATE TABLE IF NOT EXISTS OrgSharedRepo (
type OrgUserQuota (line 128) | CREATE TABLE IF NOT EXISTS OrgUserQuota (
type Repo (line 136) | CREATE TABLE IF NOT EXISTS Repo (
type RepoFileCount (line 142) | CREATE TABLE IF NOT EXISTS RepoFileCount (
type RepoGroup (line 149) | CREATE TABLE IF NOT EXISTS RepoGroup (
type RepoHead (line 159) | CREATE TABLE IF NOT EXISTS RepoHead (
type RepoHistoryLimit (line 166) | CREATE TABLE IF NOT EXISTS RepoHistoryLimit (
type RepoInfo (line 173) | CREATE TABLE IF NOT EXISTS RepoInfo (id BIGINT NOT NULL PRIMARY KEY AUTO...
type RepoOwner (line 186) | CREATE TABLE IF NOT EXISTS RepoOwner (
type RepoSize (line 194) | CREATE TABLE IF NOT EXISTS RepoSize (
type RepoStorageId (line 202) | CREATE TABLE IF NOT EXISTS RepoStorageId (
type RepoSyncError (line 209) | CREATE TABLE IF NOT EXISTS RepoSyncError (
type RepoTokenPeerInfo (line 217) | CREATE TABLE IF NOT EXISTS RepoTokenPeerInfo (
type RepoTrash (line 229) | CREATE TABLE IF NOT EXISTS RepoTrash (
type RepoUserToken (line 243) | CREATE TABLE IF NOT EXISTS RepoUserToken (
type RepoValidSince (line 253) | CREATE TABLE IF NOT EXISTS RepoValidSince (
type RoleQuota (line 260) | CREATE TABLE IF NOT EXISTS RoleQuota (
type SeafileConf (line 267) | CREATE TABLE IF NOT EXISTS SeafileConf (
type SharedRepo (line 275) | CREATE TABLE IF NOT EXISTS SharedRepo (
type SystemInfo (line 286) | CREATE TABLE IF NOT EXISTS SystemInfo (
type UserQuota (line 292) | CREATE TABLE IF NOT EXISTS UserQuota (
type UserShareQuota (line 299) | CREATE TABLE IF NOT EXISTS UserShareQuota (
type VirtualRepo (line 306) | CREATE TABLE IF NOT EXISTS VirtualRepo (
type WebAP (line 316) | CREATE TABLE IF NOT EXISTS WebAP (
type WebUploadTempFiles (line 323) | CREATE TABLE IF NOT EXISTS WebUploadTempFiles (
type RoleUploadRateLimit (line 331) | CREATE TABLE IF NOT EXISTS RoleUploadRateLimit (
type RoleDownloadRateLimit (line 338) | CREATE TABLE IF NOT EXISTS RoleDownloadRateLimit (
type UserUploadRateLimit (line 345) | CREATE TABLE IF NOT EXISTS UserUploadRateLimit (
type UserDownloadRateLimit (line 352) | CREATE TABLE IF NOT EXISTS UserDownloadRateLimit (
type OrgUserDefaultQuota (line 359) | CREATE TABLE IF NOT EXISTS OrgUserDefaultQuota (
type OrgDownloadRateLimit (line 365) | CREATE TABLE IF NOT EXISTS OrgDownloadRateLimit (
type OrgUploadRateLimit (line 372) | CREATE TABLE IF NOT EXISTS OrgUploadRateLimit (
FILE: scripts/sql/sqlite/config.sql
type Config (line 1) | CREATE TABLE IF NOT EXISTS Config (key TEXT PRIMARY KEY, value TEXT)
FILE: scripts/sql/sqlite/groupmgr.sql
type `Group` (line 1) | CREATE TABLE IF NOT EXISTS `Group` (`group_id` INTEGER PRIMARY KEY AUTOI...
type `GroupUser` (line 2) | CREATE TABLE IF NOT EXISTS `GroupUser` (`group_id` INTEGER, `user_name` ...
type groupid_username_indx (line 3) | CREATE UNIQUE INDEX IF NOT EXISTS groupid_username_indx on `GroupUser` (...
type username_indx (line 4) | CREATE INDEX IF NOT EXISTS username_indx on `GroupUser` (`user_name`)
type GroupDNPair (line 5) | CREATE TABLE IF NOT EXISTS GroupDNPair (group_id INTEGER, dn VARCHAR(255))
type GroupStructure (line 6) | CREATE TABLE IF NOT EXISTS GroupStructure (group_id INTEGER PRIMARY KEY,...
FILE: scripts/sql/sqlite/org.sql
type OrgGroup (line 1) | CREATE TABLE IF NOT EXISTS OrgGroup (org_id INTEGER, group_id INTEGER)
type groupid_indx (line 2) | CREATE INDEX IF NOT EXISTS groupid_indx on OrgGroup (group_id)
type Organization (line 5) | CREATE TABLE IF NOT EXISTS Organization (org_id INTEGER PRIMARY KEY AUTO...
type url_prefix_indx (line 6) | CREATE UNIQUE INDEX IF NOT EXISTS url_prefix_indx on Organization (url_p...
type OrgUser (line 8) | CREATE TABLE IF NOT EXISTS OrgUser (org_id INTEGER, email TEXT, is_staff...
type email_indx (line 9) | CREATE INDEX IF NOT EXISTS email_indx on OrgUser (email)
type orgid_email_indx (line 10) | CREATE UNIQUE INDEX IF NOT EXISTS orgid_email_indx on OrgUser (org_id, e...
FILE: scripts/sql/sqlite/seafile.sql
type Branch (line 1) | CREATE TABLE IF NOT EXISTS Branch (name VARCHAR(10), repo_id CHAR(40), c...
type Repo (line 2) | CREATE TABLE IF NOT EXISTS Repo (repo_id CHAR(37) PRIMARY KEY)
type RepoOwner (line 3) | CREATE TABLE IF NOT EXISTS RepoOwner (repo_id CHAR(37) PRIMARY KEY, owne...
type OwnerIndex (line 4) | CREATE INDEX IF NOT EXISTS OwnerIndex ON RepoOwner (owner_id)
type RepoGroup (line 6) | CREATE TABLE IF NOT EXISTS RepoGroup (repo_id CHAR(37), group_id INTEGER...
type groupid_repoid_indx (line 7) | CREATE UNIQUE INDEX IF NOT EXISTS groupid_repoid_indx on RepoGroup (grou...
type repogroup_repoid_index (line 8) | CREATE INDEX IF NOT EXISTS repogroup_repoid_index on RepoGroup (repo_id)
type repogroup_username_indx (line 9) | CREATE INDEX IF NOT EXISTS repogroup_username_indx on RepoGroup (user_name)
type InnerPubRepo (line 10) | CREATE TABLE IF NOT EXISTS InnerPubRepo (repo_id CHAR(37) PRIMARY KEY, p...
type OrgRepo (line 12) | CREATE TABLE IF NOT EXISTS OrgRepo (org_id INTEGER, repo_id CHAR(37), us...
type repoid_indx (line 13) | CREATE UNIQUE INDEX IF NOT EXISTS repoid_indx on OrgRepo (repo_id)
type orgid_repoid_indx (line 14) | CREATE INDEX IF NOT EXISTS orgid_repoid_indx on OrgRepo (org_id, repo_id)
type orgrepo_orgid_user_indx (line 15) | CREATE INDEX IF NOT EXISTS orgrepo_orgid_user_indx on OrgRepo (org_id, u...
type orgrepo_user_indx (line 16) | CREATE INDEX IF NOT EXISTS orgrepo_user_indx on OrgRepo (user)
type OrgGroupRepo (line 17) | CREATE TABLE IF NOT EXISTS OrgGroupRepo (org_id INTEGER, repo_id CHAR(37...
type orgid_groupid_repoid_indx (line 18) | CREATE UNIQUE INDEX IF NOT EXISTS orgid_groupid_repoid_indx on OrgGroupR...
type org_repoid_index (line 19) | CREATE INDEX IF NOT EXISTS org_repoid_index on OrgGroupRepo (repo_id)
type org_owner_indx (line 20) | CREATE INDEX IF NOT EXISTS org_owner_indx on OrgGroupRepo (owner)
type OrgInnerPubRepo (line 21) | CREATE TABLE IF NOT EXISTS OrgInnerPubRepo (org_id INTEGER, repo_id CHAR...
type RepoUserToken (line 22) | CREATE TABLE IF NOT EXISTS RepoUserToken (repo_id CHAR(37), email VARCHA...
type repo_token_indx (line 23) | CREATE UNIQUE INDEX IF NOT EXISTS repo_token_indx on RepoUserToken (repo...
type repo_token_email_indx (line 24) | CREATE INDEX IF NOT EXISTS repo_token_email_indx on RepoUserToken (email)
type RepoTokenPeerInfo (line 25) | CREATE TABLE IF NOT EXISTS RepoTokenPeerInfo (token CHAR(41) PRIMARY KEY...
type RepoSyncError (line 26) | CREATE TABLE IF NOT EXISTS RepoSyncError (token CHAR(41) PRIMARY KEY, er...
type RepoHead (line 27) | CREATE TABLE IF NOT EXISTS RepoHead (repo_id CHAR(37) PRIMARY KEY, branc...
type RepoSize (line 28) | CREATE TABLE IF NOT EXISTS RepoSize (repo_id CHAR(37) PRIMARY KEY, size ...
type RepoHistoryLimit (line 29) | CREATE TABLE IF NOT EXISTS RepoHistoryLimit (repo_id CHAR(37) PRIMARY KE...
type RepoValidSince (line 30) | CREATE TABLE IF NOT EXISTS RepoValidSince (repo_id CHAR(37) PRIMARY KEY,...
type WebAP (line 31) | CREATE TABLE IF NOT EXISTS WebAP (repo_id CHAR(37) PRIMARY KEY, access_p...
type VirtualRepo (line 32) | CREATE TABLE IF NOT EXISTS VirtualRepo (repo_id CHAR(36) PRIMARY KEY, or...
type virtualrepo_origin_repo_idx (line 33) | CREATE INDEX IF NOT EXISTS virtualrepo_origin_repo_idx ON VirtualRepo (o...
type GarbageRepos (line 34) | CREATE TABLE IF NOT EXISTS GarbageRepos (repo_id CHAR(36) PRIMARY KEY)
type RepoTrash (line 35) | CREATE TABLE IF NOT EXISTS RepoTrash (repo_id CHAR(36) PRIMARY KEY, repo...
type repotrash_owner_id_idx (line 36) | CREATE INDEX IF NOT EXISTS repotrash_owner_id_idx ON RepoTrash(owner_id)
type repotrash_org_id_idx (line 37) | CREATE INDEX IF NOT EXISTS repotrash_org_id_idx ON RepoTrash(org_id)
type RepoFileCount (line 38) | CREATE TABLE IF NOT EXISTS RepoFileCount (repo_id CHAR(36) PRIMARY KEY, ...
type FolderUserPerm (line 39) | CREATE TABLE IF NOT EXISTS FolderUserPerm (repo_id CHAR(36) NOT NULL, pa...
type folder_user_perm_idx (line 40) | CREATE INDEX IF NOT EXISTS folder_user_perm_idx ON FolderUserPerm(repo_id)
type FolderGroupPerm (line 41) | CREATE TABLE IF NOT EXISTS FolderGroupPerm (repo_id CHAR(36) NOT NULL, p...
type folder_group_perm_idx (line 42) | CREATE INDEX IF NOT EXISTS folder_group_perm_idx ON FolderGroupPerm(repo...
type FolderPermTimestamp (line 43) | CREATE TABLE IF NOT EXISTS FolderPermTimestamp (repo_id CHAR(36) PRIMARY...
type WebUploadTempFiles (line 44) | CREATE TABLE IF NOT EXISTS WebUploadTempFiles (repo_id CHAR(40) NOT NULL...
type RepoInfo (line 45) | CREATE TABLE IF NOT EXISTS RepoInfo (repo_id CHAR(36) PRIMARY KEY, name ...
type RepoInfoTypeIndex (line 46) | CREATE INDEX IF NOT EXISTS RepoInfoTypeIndex on RepoInfo (type)
type RepoStorageId (line 47) | CREATE TABLE IF NOT EXISTS RepoStorageId (repo_id CHAR(40) NOT NULL, sto...
type UserQuota (line 48) | CREATE TABLE IF NOT EXISTS UserQuota (user VARCHAR(255) PRIMARY KEY, quo...
type UserShareQuota (line 49) | CREATE TABLE IF NOT EXISTS UserShareQuota (user VARCHAR(255) PRIMARY KEY...
type OrgQuota (line 50) | CREATE TABLE IF NOT EXISTS OrgQuota (org_id INTEGER PRIMARY KEY, quota B...
type OrgUserQuota (line 51) | CREATE TABLE IF NOT EXISTS OrgUserQuota (org_id INTEGER, user VARCHAR(25...
type RoleQuota (line 52) | CREATE TABLE IF NOT EXISTS RoleQuota (role VARCHAR(255) PRIMARY KEY, quo...
type SeafileConf (line 53) | CREATE TABLE IF NOT EXISTS SeafileConf (cfg_group VARCHAR(255) NOT NULL,...
type FileLocks (line 54) | CREATE TABLE IF NOT EXISTS FileLocks (repo_id CHAR(40) NOT NULL, path TE...
type FileLocksIndex (line 55) | CREATE INDEX IF NOT EXISTS FileLocksIndex ON FileLocks (repo_id)
type FileLockTimestamp (line 56) | CREATE TABLE IF NOT EXISTS FileLockTimestamp (repo_id CHAR(40) PRIMARY K...
type SharedRepo (line 57) | CREATE TABLE IF NOT EXISTS SharedRepo (repo_id CHAR(37) , from_email VAR...
type RepoIdIndex (line 58) | CREATE INDEX IF NOT EXISTS RepoIdIndex on SharedRepo (repo_id)
type FromEmailIndex (line 59) | CREATE INDEX IF NOT EXISTS FromEmailIndex on SharedRepo (from_email)
type ToEmailIndex (line 60) | CREATE INDEX IF NOT EXISTS ToEmailIndex on SharedRepo (to_email)
type OrgSharedRepo (line 61) | CREATE TABLE IF NOT EXISTS OrgSharedRepo (org_id INTEGER, repo_id CHAR(3...
type OrgRepoIdIndex (line 62) | CREATE INDEX IF NOT EXISTS OrgRepoIdIndex on OrgSharedRepo (org_id, repo...
type OrgFromEmailIndex (line 63) | CREATE INDEX IF NOT EXISTS OrgFromEmailIndex on OrgSharedRepo (from_email)
type OrgToEmailIndex (line 64) | CREATE INDEX IF NOT EXISTS OrgToEmailIndex on OrgSharedRepo (to_email)
type OrgLibIdIndex (line 65) | CREATE INDEX IF NOT EXISTS OrgLibIdIndex on OrgSharedRepo (repo_id)
type SystemInfo (line 66) | CREATE TABLE IF NOT EXISTS SystemInfo (info_key VARCHAR(256), info_value...
FILE: scripts/sql/sqlite/user.sql
type Binding (line 1) | CREATE TABLE IF NOT EXISTS Binding (email TEXT, peer_id TEXT)
type peer_index (line 2) | CREATE UNIQUE INDEX IF NOT EXISTS peer_index on Binding (peer_id)
type EmailUser (line 4) | CREATE TABLE IF NOT EXISTS EmailUser (id INTEGER NOT NULL PRIMARY KEY AU...
type email_index (line 5) | CREATE UNIQUE INDEX IF NOT EXISTS email_index on EmailUser (email)
type reference_id_index (line 6) | CREATE UNIQUE INDEX IF NOT EXISTS reference_id_index on EmailUser (refer...
type LDAPConfig (line 8) | CREATE TABLE IF NOT EXISTS LDAPConfig (cfg_group VARCHAR(255) NOT NULL, ...
type LDAPUsers (line 10) | CREATE TABLE IF NOT EXISTS LDAPUsers (id INTEGER PRIMARY KEY AUTOINCREME...
type ldapusers_email_index (line 11) | CREATE UNIQUE INDEX IF NOT EXISTS ldapusers_email_index on LDAPUsers(email)
type ldapusers_reference_id_index (line 12) | CREATE UNIQUE INDEX IF NOT EXISTS ldapusers_reference_id_index on LDAPUs...
type UserRole (line 14) | CREATE TABLE IF NOT EXISTS UserRole (email TEXT, role TEXT, is_manual_se...
type userrole_email_index (line 15) | CREATE INDEX IF NOT EXISTS userrole_email_index on UserRole (email)
type userrole_userrole_index (line 16) | CREATE UNIQUE INDEX IF NOT EXISTS userrole_userrole_index on UserRole (e...
FILE: server/access-file.c
type file_type_map (line 35) | struct file_type_map {
type SendBlockData (line 40) | typedef struct SendBlockData {
type SendfileData (line 58) | typedef struct SendfileData {
type SendFileRangeData (line 80) | typedef struct SendFileRangeData {
type SendDirData (line 100) | typedef struct SendDirData {
type file_type_map (line 122) | struct file_type_map
function free_sendblock_data (line 160) | static void
function free_sendfile_data (line 173) | static void
function free_send_file_range_data (line 191) | static void
function free_senddir_data (line 205) | static void
function write_block_data_cb (line 218) | static void
function write_data_cb (line 283) | static void
function write_dir_data_cb (line 429) | static void
function my_block_event_cb (line 470) | static void
function my_event_cb (line 481) | static void
function file_range_event_cb (line 492) | static void
function my_dir_event_cb (line 503) | static void
function gboolean (line 537) | static gboolean
function do_file (line 555) | static int
function BlockHandle (line 693) | static BlockHandle *
function finish_file_range_request (line 756) | static void
function write_file_range_cb (line 773) | static void
function gboolean (line 841) | static gboolean
function set_resp_disposition (line 914) | static void
function do_file_range (line 936) | static int
function start_download_zip_file (line 1057) | static int
function set_etag (line 1133) | static void
function set_no_cache (line 1143) | static void
function gboolean (line 1156) | static gboolean
function access_zip_cb (line 1189) | static void
function access_cb (line 1385) | static void
function access_v2_cb (line 1504) | static void
function do_block (line 1656) | static int
function access_blks_cb (line 1747) | static void
function access_link_cb (line 1831) | static void
function evhtp_res (line 2328) | static evhtp_res
function evhtp_res (line 2344) | static evhtp_res
function access_file_init (line 2360) | int
FILE: server/change-set.c
type _ChangeSetDir (line 12) | struct _ChangeSetDir {
type ChangeSetDir (line 19) | typedef struct _ChangeSetDir ChangeSetDir;
type _ChangeSetDirent (line 21) | struct _ChangeSetDirent {
type ChangeSetDirent (line 33) | typedef struct _ChangeSetDirent ChangeSetDirent;
function ChangeSetDirent (line 37) | static ChangeSetDirent *
function ChangeSetDirent (line 53) | static ChangeSetDirent *
function SeafDirent (line 60) | static SeafDirent *
function changeset_dirent_free (line 70) | static void
function add_dent_to_dir (line 86) | static void
function remove_dent_from_dir (line 94) | static void
function ChangeSetDir (line 106) | static ChangeSetDir *
function changeset_dir_free (line 128) | static void
function ChangeSetDir (line 137) | static ChangeSetDir *
function gint (line 143) | static gint
function SeafDir (line 151) | static SeafDir *
function ChangeSet (line 178) | ChangeSet *
function changeset_free (line 196) | void
function ChangeSetDirent (line 206) | static ChangeSetDirent *
function remove_from_changeset_recursive (line 281) | static void
function remove_from_changeset (line 314) | void
FILE: server/change-set.h
type _ChangeSetDir (line 9) | struct _ChangeSetDir
type _ChangeSet (line 11) | struct _ChangeSet {
type ChangeSet (line 16) | typedef struct _ChangeSet ChangeSet;
FILE: server/copy-mgr.c
type _SeafCopyManagerPriv (line 18) | struct _SeafCopyManagerPriv {
function copy_task_free (line 24) | static void
function SeafCopyManager (line 33) | SeafCopyManager *
function seaf_copy_manager_start (line 55) | int
function SeafileCopyTask (line 63) | SeafileCopyTask *
type CopyThreadData (line 90) | struct CopyThreadData {
type CopyThreadData (line 103) | typedef struct CopyThreadData CopyThreadData;
function copy_done (line 117) | static void
type CopyThreadData (line 146) | struct CopyThreadData
function seaf_copy_manager_cancel_task (line 178) | int
FILE: server/copy-mgr.h
type _SeafileSession (line 12) | struct _SeafileSession
type _SeafCopyManagerPriv (line 13) | struct _SeafCopyManagerPriv
type _SeafileCopyTask (line 14) | struct _SeafileCopyTask
type _SeafCopyManager (line 16) | struct _SeafCopyManager {
type SeafCopyManager (line 23) | typedef struct _SeafCopyManager SeafCopyManager;
type SeafCopyManagerPriv (line 24) | typedef struct _SeafCopyManagerPriv SeafCopyManagerPriv;
Condensed preview — 284 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,104K chars).
[
{
"path": ".github/workflows/ci.yml",
"chars": 399,
"preview": "name: Seafile CI\n\non: [push, pull_request]\n\njobs:\n build:\n runs-on: ubuntu-latest\n\n steps:\n - uses: actions/"
},
{
"path": ".github/workflows/golangci-lint.yml",
"chars": 954,
"preview": "name: golangci-lint\n\non: [push, pull_request]\n\npermissions:\n contents: read\n # Optional: allow read access to pull req"
},
{
"path": ".gitignore",
"chars": 1170,
"preview": "*~\n*.bak\n*.o\n*.exe\ncscope*\n*#\nMakefile.in\nltmain.sh\nlibtool\n*.lo\n*.la\ninstall-sh\ndepcomp\nconfig.guess\nconfig.h\nconfig.lo"
},
{
"path": "LICENSE.txt",
"chars": 34603,
"preview": "This program is released under Affero GPLv3, with the following additional\npermission to link with OpenSSL library.\n\nIf "
},
{
"path": "Makefile.am",
"chars": 595,
"preview": "MAKE_CLIENT =\n\nif WIN32\n MAKE_CONTROLLER =\nelse\n MAKE_CONTROLLER = controller\nendif\n\nif COMPILE_FUSE\n MAKE_FUSE = fus"
},
{
"path": "README.markdown",
"chars": 1130,
"preview": "Seafile Server Core [](http://travi"
},
{
"path": "README.testing.md",
"chars": 586,
"preview": "# Seafile Server Tests\n\n## Run it locally\n\nTo run the tests, you need to install pytest first:\n\n```sh\npip install -r ci/"
},
{
"path": "autogen.sh",
"chars": 3412,
"preview": "#!/bin/bash\n# Run this to generate all the initial makefiles, etc.\n\n: ${AUTOCONF=autoconf}\n: ${AUTOHEADER=autoheader}\n: "
},
{
"path": "ci/install-deps.sh",
"chars": 493,
"preview": "#!/bin/bash\n\nset -e -x\n\nSCRIPT=${BASH_SOURCE[0]}\nTESTS_DIR=$(dirname \"${SCRIPT}\")/..\nSETUP_DIR=${TESTS_DIR}/ci\n\ncd $SETU"
},
{
"path": "ci/requirements.txt",
"chars": 123,
"preview": "termcolor>=1.1.0\nrequests>=2.8.0\npytest>=3.3.2\nbackports.functools_lru_cache>=1.4\ntenacity>=4.8.0\nfuture\nrequests-toolbe"
},
{
"path": "ci/run.py",
"chars": 7817,
"preview": "#!/usr/bin/env python\n\"\"\"\nInstall dir: ~/opt/local\nData dir: /tmp/haiwen\n\"\"\"\n\nimport argparse\nimport glob\nimport json\nim"
},
{
"path": "ci/serverctl.py",
"chars": 8284,
"preview": "#!/usr/bin/env python\n#coding: UTF-8\n\nimport argparse\nimport glob\nimport logging\nimport os\nimport re\nimport sys\nfrom col"
},
{
"path": "ci/utils.py",
"chars": 2165,
"preview": "#coding: UTF-8\n\nimport logging\nimport os\nimport re\nimport sys\nfrom contextlib import contextmanager\nfrom os.path import "
},
{
"path": "common/Makefile.am",
"chars": 460,
"preview": "SUBDIRS = cdc\n\nproc_headers = \\\n\t$(addprefix processors/, \\\n\tobjecttx-common.h)\n\nnoinst_HEADERS = \\\n\tdiff-simple.h \\\n\tse"
},
{
"path": "common/block-backend-fs.c",
"chars": 13426,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#ifndef _WIN32_WINNT\n#define _WIN32_WINNT"
},
{
"path": "common/block-backend.c",
"chars": 1228,
"preview": "\n#include \"common.h\"\n\n#include \"log.h\"\n\n#include \"block-backend.h\"\n\nextern BlockBackend *\nblock_backend_fs_new (const ch"
},
{
"path": "common/block-backend.h",
"chars": 2202,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#ifndef BLOCK_BACKEND_H\n#define BLOCK_BAC"
},
{
"path": "common/block-mgr.c",
"chars": 7509,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#include \"common.h\"\n\n#include \"seafile-se"
},
{
"path": "common/block-mgr.h",
"chars": 4595,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#ifndef SEAF_BLOCK_MGR_H\n#define SEAF_BLO"
},
{
"path": "common/block-tx-utils.c",
"chars": 8168,
"preview": "#include \"common.h\"\n#define DEBUG_FLAG SEAFILE_DEBUG_TRANSFER\n#include \"log.h\"\n\n#include \"utils.h\"\n#include \"block-tx-ut"
},
{
"path": "common/block-tx-utils.h",
"chars": 3301,
"preview": "#ifndef BLOCK_TX_UTILS_H\n#define BLOCK_TX_UTILS_H\n\n#include <event2/buffer.h>\n#include <event2/util.h>\n#include <openssl"
},
{
"path": "common/block.h",
"chars": 627,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#ifndef BLOCK_H\n#define BLOCK_H\n\ntypedef "
},
{
"path": "common/branch-mgr.c",
"chars": 20695,
"preview": "#include \"common.h\"\n\n#include \"log.h\"\n\n#ifndef SEAFILE_SERVER\n#include \"db.h\"\n#else\n#include \"seaf-db.h\"\n#endif\n\n#includ"
},
{
"path": "common/branch-mgr.h",
"chars": 2742,
"preview": "#ifndef SEAF_BRANCH_MGR_H\n#define SEAF_BRANCH_MGR_H\n\n#include \"commit-mgr.h\"\n#define NO_BRANCH \"-\"\n\ntypedef struct _Seaf"
},
{
"path": "common/cdc/Makefile.am",
"chars": 334,
"preview": "AM_CFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/lib \\\n\t-Wall @GLIB2_CFLAGS@ @MSVC_CFLAGS@\n\nnoinst_LTLIBRARIES = libcd"
},
{
"path": "common/cdc/cdc.c",
"chars": 8274,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#include \"common.h\"\n\n#include \"log.h\"\n\n#i"
},
{
"path": "common/cdc/cdc.h",
"chars": 1788,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#ifndef _CDC_H\n#define _CDC_H\n\n#include <"
},
{
"path": "common/cdc/rabin-checksum.c",
"chars": 4092,
"preview": "#include <sys/types.h>\n#include \"rabin-checksum.h\"\n\n#ifdef WIN32\n#include <stdint.h>\n#ifndef u_int\ntypedef unsigned int "
},
{
"path": "common/cdc/rabin-checksum.h",
"chars": 222,
"preview": "#ifndef _RABIN_CHECKSUM_H\n#define _RABIN_CHECKSUM_H\n\nunsigned int rabin_checksum(char *buf, int len);\n\nunsigned int rabi"
},
{
"path": "common/commit-mgr.c",
"chars": 29796,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#include \"common.h\"\n\n#include \"log.h\"\n\n#i"
},
{
"path": "common/commit-mgr.h",
"chars": 6588,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#ifndef SEAF_COMMIT_MGR_H\n#define SEAF_CO"
},
{
"path": "common/common.h",
"chars": 1415,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#ifndef COMMON_H\n#define COMMON_H\n\n#ifdef"
},
{
"path": "common/config-mgr.c",
"chars": 6387,
"preview": "#include \"common.h\"\n#include \"config-mgr.h\"\n#include \"seaf-db.h\"\n#include \"log.h\"\n\nint\nseaf_cfg_manager_init (SeafCfgMan"
},
{
"path": "common/config-mgr.h",
"chars": 1452,
"preview": "#ifndef SEAF_CONFIG_MGR_H\n#define SEAF_CONFIG_MGR_H\n\ntypedef struct _SeafCfgManager SeafCfgManager;\n#include \"seafile-se"
},
{
"path": "common/diff-simple.c",
"chars": 26239,
"preview": "#include \"common.h\"\n#include \"diff-simple.h\"\n#include \"utils.h\"\n#include \"log.h\"\n\nDiffEntry *\ndiff_entry_new (char type,"
},
{
"path": "common/diff-simple.h",
"chars": 3488,
"preview": "#ifndef DIFF_SIMPLE_H\n#define DIFF_SIMPLE_H\n\n#include <glib.h>\n#include \"seafile-session.h\"\n\n#define DIFF_TYPE_WORKTREE "
},
{
"path": "common/fs-mgr.c",
"chars": 88966,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#ifndef _GNU_SOURECE\n#define _GNU_SOURCE\n"
},
{
"path": "common/fs-mgr.h",
"chars": 14352,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#ifndef SEAF_FILE_MGR_H\n#define SEAF_FILE"
},
{
"path": "common/group-mgr.c",
"chars": 53321,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#include \"common.h\"\n\n#include \"seafile-se"
},
{
"path": "common/group-mgr.h",
"chars": 6240,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#ifndef GROUP_MGR_H\n#define GROUP_MGR_H\n\n"
},
{
"path": "common/log.c",
"chars": 6499,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#include \"common.h\"\n\n#include <stdio.h>\n#"
},
{
"path": "common/log.h",
"chars": 1342,
"preview": "#ifndef LOG_H\n#define LOG_H\n\n#define SEAFILE_DOMAIN g_quark_from_string(\"seafile\")\n\n#ifndef seaf_warning\n#define seaf_wa"
},
{
"path": "common/merge-new.c",
"chars": 26537,
"preview": "#include \"common.h\"\n\n#include \"seafile-session.h\"\n#include \"merge-new.h\"\n#include \"vc-common.h\"\n\n#define DEBUG_FLAG SEAF"
},
{
"path": "common/merge-new.h",
"chars": 1027,
"preview": "#ifndef MERGE_NEW_H\n#define MERGE_NEW_H\n\n#include \"common.h\"\n\n#include \"fs-mgr.h\"\n\nstruct MergeOptions;\n\ntypedef int (*M"
},
{
"path": "common/mq-mgr.c",
"chars": 1888,
"preview": "#include \"common.h\"\n#include \"log.h\"\n#include \"utils.h\"\n#include \"mq-mgr.h\"\n\ntypedef struct SeafMqManagerPriv {\n // c"
},
{
"path": "common/mq-mgr.h",
"chars": 528,
"preview": "#ifndef SEAF_MQ_MANAGER_H\n#define SEAF_MQ_MANAGER_H\n\n#include <jansson.h>\n\n#define SEAFILE_SERVER_CHANNEL_EVENT \"seaf_se"
},
{
"path": "common/obj-backend-fs.c",
"chars": 13275,
"preview": "#ifndef _WIN32_WINNT\n#define _WIN32_WINNT 0x500\n#endif\n\n#include \"common.h\"\n#include \"utils.h\"\n#include \"obj-backend.h\"\n"
},
{
"path": "common/obj-backend-riak.c",
"chars": 3541,
"preview": "#include \"common.h\"\n#include \"log.h\"\n#include \"obj-backend.h\"\n\n#ifdef RIAK_BACKEND\n\n#include \"riak-client.h\"\n\n#include <"
},
{
"path": "common/obj-backend.h",
"chars": 1713,
"preview": "#ifndef OBJ_BACKEND_H\n#define OBJ_BACKEND_H\n\n#include <glib.h>\n#include \"obj-store.h\"\n\ntypedef struct ObjBackend ObjBack"
},
{
"path": "common/obj-cache.c",
"chars": 4987,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#include \"common.h\"\n\n#define DEBUG_FLAG S"
},
{
"path": "common/obj-cache.h",
"chars": 2188,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#ifndef OBJ_CACHE_H\n#define OBJ_CACHE_H\n\n"
},
{
"path": "common/obj-store.c",
"chars": 3742,
"preview": "#include \"common.h\"\n\n#include \"log.h\"\n\n#include \"seafile-session.h\"\n\n#include \"utils.h\"\n\n#include \"obj-backend.h\"\n#inclu"
},
{
"path": "common/obj-store.h",
"chars": 2178,
"preview": "#ifndef OBJ_STORE_H\n#define OBJ_STORE_H\n\n#include <glib.h>\n#include <sys/types.h>\n\nstruct _SeafileSession;\nstruct SeafOb"
},
{
"path": "common/object-list.c",
"chars": 1221,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#include \"common.h\"\n\n#include \"object-lis"
},
{
"path": "common/object-list.h",
"chars": 802,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#ifndef OBJECT_LIST_H\n#define OBJECT_LIST"
},
{
"path": "common/org-mgr.c",
"chars": 26064,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#include \"common.h\"\n\n#include \"seafile-se"
},
{
"path": "common/org-mgr.h",
"chars": 5076,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#ifndef _ORG_MGR_H_\n#define _ORG_MGR_H_\n\n"
},
{
"path": "common/password-hash.c",
"chars": 4875,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#include <string.h>\n#include <glib.h>\n#in"
},
{
"path": "common/password-hash.h",
"chars": 607,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#ifndef _PASSWORD_HASH_H\n#define _PASSWOR"
},
{
"path": "common/processors/objecttx-common.h",
"chars": 1379,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#ifndef OBJECTTX_COMMON_H\n#define OBJECTT"
},
{
"path": "common/redis-cache.c",
"chars": 11756,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#include \"common.h\"\n\n#include <hiredis.h>"
},
{
"path": "common/redis-cache.h",
"chars": 304,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#ifndef REDIS_CACHE_H\n#define REDIS_CACHE"
},
{
"path": "common/rpc-service.c",
"chars": 171367,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#include \"common.h\"\n#include <glib/gstdio"
},
{
"path": "common/seaf-db.c",
"chars": 41775,
"preview": "\n#include \"common.h\"\n\n#include \"log.h\"\n\n#include \"seaf-db.h\"\n\n#include <stdarg.h>\n#ifdef HAVE_MYSQL\n#include <mysql.h>\n#"
},
{
"path": "common/seaf-db.h",
"chars": 3303,
"preview": "#ifndef SEAF_DB_H\n#define SEAF_DB_H\n\nenum {\n SEAF_DB_TYPE_SQLITE,\n SEAF_DB_TYPE_MYSQL,\n SEAF_DB_TYPE_PGSQL,\n};\n"
},
{
"path": "common/seaf-utils.c",
"chars": 15454,
"preview": "#include \"common.h\"\n\n#include \"log.h\"\n\n#include \"seafile-session.h\"\n#include \"seaf-utils.h\"\n#include \"seaf-db.h\"\n#includ"
},
{
"path": "common/seaf-utils.h",
"chars": 693,
"preview": "#ifndef SEAF_UTILS_H\n#define SEAF_UTILS_H\n\n#include <searpc-client.h>\n\nstruct _SeafileSession;\n\nchar *\nseafile_session_g"
},
{
"path": "common/seafile-crypt.c",
"chars": 18225,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#include <string.h>\n#include <glib.h>\n#in"
},
{
"path": "common/seafile-crypt.h",
"chars": 4225,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n/*\n Description:\n \n The function pair "
},
{
"path": "common/sync-repo-common.h",
"chars": 582,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#ifndef SYNC_REPO_COMMON\n#define SYNC_REP"
},
{
"path": "common/user-mgr.c",
"chars": 39315,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#include \"common.h\"\n\n#include <sys/stat.h"
},
{
"path": "common/user-mgr.h",
"chars": 5523,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#ifndef CCNET_USER_MGR_H\n#define CCNET_US"
},
{
"path": "common/vc-common.c",
"chars": 18887,
"preview": "#include \"common.h\"\n\n#include \"seafile-session.h\"\n#include \"vc-common.h\"\n\n#include \"log.h\"\n#include \"seafile-error.h\"\n\ns"
},
{
"path": "common/vc-common.h",
"chars": 1421,
"preview": "#ifndef VC_COMMON_H\n#define VC_COMMON_H\n\n#include \"commit-mgr.h\"\n\nSeafCommit *\nget_merge_base (SeafCommit *head, SeafCom"
},
{
"path": "configure.ac",
"chars": 8069,
"preview": "dnl Process this file with autoconf to produce a configure script.\n\n\nAC_PREREQ(2.61)\nAC_INIT([seafile], [6.0.1], [freepl"
},
{
"path": "controller/Makefile.am",
"chars": 528,
"preview": "bin_PROGRAMS = seafile-controller\n\nAM_CFLAGS = \\\n\t-DSEAFILE_SERVER \\\n\t-I$(top_srcdir)/include \\\n\t-I$(top_srcdir)/lib \\\n\t"
},
{
"path": "controller/seafile-controller.c",
"chars": 25442,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#include \"common.h\"\n\n#include <sys/types."
},
{
"path": "controller/seafile-controller.h",
"chars": 1348,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n/*\n * Seafile-controller is responsible f"
},
{
"path": "doc/Makefile.am",
"chars": 34,
"preview": "EXTRA_DIST = seafile-tutorial.doc\n"
},
{
"path": "fileserver/.golangci.yml",
"chars": 146,
"preview": "run:\n timeout: 2m\n\nlinters:\n enable:\n - govet\n - gosimple\n - ineffassign\n - staticcheck\n - unused\n - gofmt"
},
{
"path": "fileserver/blockmgr/blockmgr.go",
"chars": 1055,
"preview": "// Package blockmgr provides operations on blocks\npackage blockmgr\n\nimport (\n\t\"github.com/haiwen/seafile-server/fileserv"
},
{
"path": "fileserver/blockmgr/blockmgr_test.go",
"chars": 1944,
"preview": "package blockmgr\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"os\"\n\t\"path\"\n\t\"testing\"\n)\n\nconst (\n\tblockID = \"0401fc662e3bc87a41f29"
},
{
"path": "fileserver/commitmgr/commitmgr.go",
"chars": 4921,
"preview": "// Package commitmgr manages commit objects.\npackage commitmgr\n\nimport (\n\t\"bytes\"\n\t\"crypto/sha1\"\n\t\"encoding/binary\"\n\t\"en"
},
{
"path": "fileserver/commitmgr/commitmgr_test.go",
"chars": 1528,
"preview": "package commitmgr\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"testing\"\n\t\"time\"\n)\n\nconst (\n\tcommitID = \"0401fc662e3bc87a41f299a907c05"
},
{
"path": "fileserver/commitmgr/null.go",
"chars": 2718,
"preview": "package commitmgr\n\nimport (\n\t\"bytes\"\n\t\"database/sql\"\n\t\"encoding/json\"\n\t\"fmt\"\n)\n\n// nullBytes is a JSON null literal\nvar "
},
{
"path": "fileserver/crypt.go",
"chars": 1911,
"preview": "package main\n\nimport (\n\t\"bytes\"\n\t\"crypto/aes\"\n\t\"crypto/cipher\"\n)\n\ntype seafileCrypt struct {\n\tkey []byte\n\tiv []"
},
{
"path": "fileserver/diff/diff.go",
"chars": 14244,
"preview": "package diff\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"io\"\n\t\"path/filepath\"\n\t\"strings\"\n\n\t\"github.com/haiwen/seafile-server/fileserve"
},
{
"path": "fileserver/diff/diff_test.go",
"chars": 6438,
"preview": "package diff\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n\t\"syscall\"\n\t\"testing\"\n\n\t\"github.com/haiwen/seafile-server/fileserver/fsmg"
},
{
"path": "fileserver/fileop.go",
"chars": 108051,
"preview": "package main\n\nimport (\n\t\"archive/zip\"\n\t\"bytes\"\n\t\"context\"\n\t\"crypto/sha1\"\n\t\"encoding/hex\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fm"
},
{
"path": "fileserver/fileserver.go",
"chars": 13683,
"preview": "// Main package for Seafile file server.\npackage main\n\nimport (\n\t\"crypto/tls\"\n\t\"crypto/x509\"\n\t\"database/sql\"\n\t\"flag\"\n\t\"f"
},
{
"path": "fileserver/fsmgr/fsmgr.go",
"chars": 21642,
"preview": "// Package fsmgr manages fs objects\npackage fsmgr\n\nimport (\n\t\"bytes\"\n\t\"compress/zlib\"\n\t\"crypto/sha1\"\n\t\"encoding/hex\"\n\t\"f"
},
{
"path": "fileserver/fsmgr/fsmgr_test.go",
"chars": 2561,
"preview": "package fsmgr\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"testing\"\n)\n\nconst (\n\tseafileConfPath = \"/tmp/conf\"\n\tseafileDataDir = \"/tmp/conf/"
},
{
"path": "fileserver/go.mod",
"chars": 868,
"preview": "module github.com/haiwen/seafile-server/fileserver\n\ngo 1.22\n\nrequire (\n\tgithub.com/dgraph-io/ristretto v0.2.0\n\tgithub.co"
},
{
"path": "fileserver/go.sum",
"chars": 7263,
"preview": "github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=\ngithub.com/cespare/xxhash/v2 v2.1.2/"
},
{
"path": "fileserver/http_code.go",
"chars": 280,
"preview": "package main\n\nconst (\n\tseafHTTPResBadFileName = 440\n\tseafHTTPResExists = 441\n\tseafHTTPResNotExists = 441\n\ts"
},
{
"path": "fileserver/merge.go",
"chars": 11761,
"preview": "package main\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"path/filepath\"\n\t\"sort\"\n\t\"strings\"\n\t\"time\"\n\n\t\"githu"
},
{
"path": "fileserver/merge_test.go",
"chars": 13257,
"preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"syscall\"\n\t\"testing\"\n\n\t\"github.com/haiwen/seafile-server/fileserver/commitmgr\"\n\t\"gi"
},
{
"path": "fileserver/metrics/metrics.go",
"chars": 3249,
"preview": "package metrics\n\nimport (\n\t\"container/list\"\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"runtime/debug\"\n\t\"sync\"\n\t\"ti"
},
{
"path": "fileserver/objstore/backend_fs.go",
"chars": 2184,
"preview": "// Implementation of file system storage backend.\npackage objstore\n\nimport (\n\t\"io\"\n\t\"os\"\n\t\"path\"\n)\n\ntype fsBackend struc"
},
{
"path": "fileserver/objstore/objstore.go",
"chars": 1935,
"preview": "// Package objstore provides operations for commit, fs and block objects.\n// It is low-level package used by commitmgr, "
},
{
"path": "fileserver/objstore/objstore_test.go",
"chars": 2134,
"preview": "package objstore\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path\"\n\t\"testing\"\n)\n\nconst (\n\ttestFile = \"output.data\"\n\tseafileConfPath "
},
{
"path": "fileserver/option/option.go",
"chars": 11684,
"preview": "package option\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\tlog \"github.com/sirupsen/logrus\"\n"
},
{
"path": "fileserver/quota.go",
"chars": 2250,
"preview": "package main\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"fmt\"\n\n\t\"github.com/haiwen/seafile-server/fileserver/option\"\n\t\"github"
},
{
"path": "fileserver/repomgr/repomgr.go",
"chars": 22415,
"preview": "// Package repomgr manages repo objects and file operations in repos.\npackage repomgr\n\nimport (\n\t\"context\"\n\t\"database/sq"
},
{
"path": "fileserver/repomgr/repomgr_test.go",
"chars": 1883,
"preview": "package repomgr\n\nimport (\n\t\"database/sql\"\n\t\"fmt\"\n\t\"os\"\n\t\"testing\"\n\n\t_ \"github.com/go-sql-driver/mysql\"\n\t\"github.com/haiw"
},
{
"path": "fileserver/searpc/searpc.go",
"chars": 3772,
"preview": "// Package searpc implements searpc client protocol with unix pipe transport.\npackage searpc\n\nimport (\n\t\"bufio\"\n\t\"encodi"
},
{
"path": "fileserver/searpc/searpc_test.go",
"chars": 1607,
"preview": "package searpc\n\nimport (\n\t\"os\"\n\t\"testing\"\n)\n\nconst (\n\trepoName = \"repo\"\n\tuserName = \"seafile@seafile.com\"\n\tencVersio"
},
{
"path": "fileserver/share/group/group.go",
"chars": 74,
"preview": "// Package group manages group membership and group shares.\npackage group\n"
},
{
"path": "fileserver/share/public/public.go",
"chars": 62,
"preview": "// Package public manager inner public shares.\npackage public\n"
},
{
"path": "fileserver/share/share.go",
"chars": 17359,
"preview": "// Package share manages share relations.\n// share: manages personal shares and provide high level permission check func"
},
{
"path": "fileserver/size_sched.go",
"chars": 6412,
"preview": "package main\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"time\"\n\n\t\"gopkg.in/ini.v1\"\n\n\t\"database/sql\"\n"
},
{
"path": "fileserver/sync_api.go",
"chars": 40939,
"preview": "package main\n\nimport (\n\t\"bytes\"\n\t\"context\"\n\t\"database/sql\"\n\t\"encoding/binary\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"html\"\n"
},
{
"path": "fileserver/utils/dup2.go",
"chars": 132,
"preview": "//go:build !(linux && arm64)\n\npackage utils\n\nimport (\n\t\"syscall\"\n)\n\nfunc Dup(from, to int) error {\n\treturn syscall.Dup2("
},
{
"path": "fileserver/utils/dup3.go",
"chars": 132,
"preview": "//go:build linux && arm64\n\npackage utils\n\nimport (\n\t\"syscall\"\n)\n\nfunc Dup(from, to int) error {\n\treturn syscall.Dup3(fro"
},
{
"path": "fileserver/utils/http.go",
"chars": 1472,
"preview": "package utils\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"strings\"\n\t\"time\"\n)\n\nfunc GetAuthorization"
},
{
"path": "fileserver/utils/utils.go",
"chars": 1711,
"preview": "package utils\n\nimport (\n\t\"fmt\"\n\t\"time\"\n\n\tjwt \"github.com/golang-jwt/jwt/v5\"\n\t\"github.com/google/uuid\"\n\t\"github.com/haiwe"
},
{
"path": "fileserver/virtual_repo.go",
"chars": 9975,
"preview": "package main\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"path/filepath\"\n\t\"strings\"\n\t\"sync\"\n\t\"time\"\n\n\t\"math/rand\"\n\n\t\"github.com/haiwen/s"
},
{
"path": "fileserver/workerpool/workerpool.go",
"chars": 1170,
"preview": "package workerpool\n\nimport (\n\t\"runtime/debug\"\n\n\t\"github.com/dgraph-io/ristretto/z\"\n\tlog \"github.com/sirupsen/logrus\"\n)\n\n"
},
{
"path": "fuse/Makefile.am",
"chars": 1581,
"preview": "AM_CFLAGS = -DPKGDATADIR=\\\"$(pkgdatadir)\\\" \\\n\t-DPACKAGE_DATA_DIR=\\\"\"$(pkgdatadir)\"\\\" \\\n\t-DSEAFILE_SERVER \\\n\t-I$(top_srcd"
},
{
"path": "fuse/file.c",
"chars": 2848,
"preview": "#include \"common.h\"\n\n#define FUSE_USE_VERSION 26\n#include <fuse.h>\n\n#include <glib.h>\n#include <glib-object.h>\n\n#includ"
},
{
"path": "fuse/getattr.c",
"chars": 5179,
"preview": "#include \"common.h\"\n\n#define FUSE_USE_VERSION 26\n#include <fuse.h>\n\n#include <glib.h>\n#include <glib-object.h>\n\n#includ"
},
{
"path": "fuse/readdir.c",
"chars": 6160,
"preview": "#include \"common.h\"\n\n#define FUSE_USE_VERSION 26\n#include <fuse.h>\n\n#include <glib.h>\n#include <glib-object.h>\n\n#includ"
},
{
"path": "fuse/repo-mgr.c",
"chars": 10068,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#include \"common.h\"\n#include <glib/gstdio"
},
{
"path": "fuse/repo-mgr.h",
"chars": 2415,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#ifndef SEAF_REPO_MGR_H\n#define SEAF_REPO"
},
{
"path": "fuse/seaf-fuse.c",
"chars": 9296,
"preview": "#include \"common.h\"\n\n#include <unistd.h>\n#include <getopt.h>\n\n#define FUSE_USE_VERSION 26\n#include <fuse.h>\n#include <f"
},
{
"path": "fuse/seaf-fuse.h",
"chars": 922,
"preview": "#ifndef SEAF_FUSE_H\n#define SEAF_FUSE_H\n\n#include \"seafile-session.h\"\n\nint parse_fuse_path (const char *path,\n "
},
{
"path": "fuse/seafile-session.c",
"chars": 5137,
"preview": "#include \"common.h\"\n\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <unistd.h>\n\n#include <utils.h>\n#include <loca"
},
{
"path": "fuse/seafile-session.h",
"chars": 1351,
"preview": "#ifndef SEAFILE_SESSION_H\n#define SEAFILE_SESSION_H\n\n#include <stdint.h>\n#include <glib.h>\n\n#include <seaf-db.h>\n\n#inclu"
},
{
"path": "include/Makefile.am",
"chars": 48,
"preview": "\nnoinst_HEADERS = seafile-rpc.h seafile-error.h\n"
},
{
"path": "include/seafile-error.h",
"chars": 958,
"preview": "#ifndef SEAFILE_ERROR_H\n#define SEAFILE_ERROR_H\n\n#define SEAF_ERR_GENERAL 500\n#define SEAF_ERR_BAD_REPO 501"
},
{
"path": "include/seafile-rpc.h",
"chars": 41394,
"preview": "\n#ifndef _SEAFILE_RPC_H\n#define _SEAFILE_RPC_H\n\n#include \"seafile-object.h\"\n\n/**\n * seafile_get_session_info:\n *\n * Retu"
},
{
"path": "lib/Makefile.am",
"chars": 2252,
"preview": "pcfiles = libseafile.pc\npkgconfig_DATA = $(pcfiles)\npkgconfigdir = $(libdir)/pkgconfig\n\nAM_CPPFLAGS = @GLIB2_CFLAGS@ -I$"
},
{
"path": "lib/bloom-filter.c",
"chars": 3776,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#include <limits.h>\n#include <stdint.h>\n#"
},
{
"path": "lib/bloom-filter.h",
"chars": 567,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#ifndef __BLOOM_H__\n#define __BLOOM_H__\n\n"
},
{
"path": "lib/branch.vala",
"chars": 505,
"preview": "// compile this file with `valac --pkg posix repo.vala -C -H repo.h`\n\nnamespace Seafile {\n\npublic class Branch : Object "
},
{
"path": "lib/ccnetobj.vala",
"chars": 1170,
"preview": "\n\nnamespace Ccnet {\n\n\npublic class EmailUser : Object {\n\n public int id { get; set; }\n public string email { get; "
},
{
"path": "lib/commit.vala",
"chars": 1805,
"preview": "// compile this file with `valac --pkg posix repo.vala -C -H repo.h`\n\nnamespace Seafile {\n\npublic class Commit : Object "
},
{
"path": "lib/copy-task.vala",
"chars": 438,
"preview": "namespace Seafile {\n\npublic class CopyTask : Object {\n public int64 done { set; get; }\n public int64 total {"
},
{
"path": "lib/crypt.vala",
"chars": 136,
"preview": "namespace Seafile {\n\npublic class CryptKey : Object {\n public string key { set; get; }\n public string iv { s"
},
{
"path": "lib/db.c",
"chars": 5054,
"preview": "\n#include <glib.h>\n#include <unistd.h>\n\n#include \"db.h\"\n\nint\nsqlite_open_db (const char *db_path, sqlite3 **db)\n{\n in"
},
{
"path": "lib/db.h",
"chars": 885,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#ifndef DB_UTILS_H\n#define DB_UTILS_H\n\n#i"
},
{
"path": "lib/dir.vala",
"chars": 652,
"preview": "namespace Seafile {\n\n\tpublic class Dir : Object {\n\n\t\t// _id is for fast access from c code. id is for\n\t\t// vala to autom"
},
{
"path": "lib/dirent.vala",
"chars": 842,
"preview": "namespace Seafile {\n\npublic class Dirent : Object {\n\n // _id is for fast access from c code. id is for\n\t// vala to au"
},
{
"path": "lib/file.vala",
"chars": 414,
"preview": "namespace Seafile {\n\npublic class File : Object {\n\n // _id is for fast access from c code. id is for\n\t// vala to auto"
},
{
"path": "lib/include.h",
"chars": 633,
"preview": "\n#include <config.h>\n#include <stdint.h>\n#include <unistd.h>\n#include <stdlib.h>\n#include <string.h>\n#include <errno.h>\n"
},
{
"path": "lib/job-mgr.c",
"chars": 3843,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#if defined(__FreeBSD__) || defined(__Net"
},
{
"path": "lib/job-mgr.h",
"chars": 1178,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n/**\n * Job Manager manages long term jobs"
},
{
"path": "lib/libseafile.pc.in",
"chars": 300,
"preview": "prefix=(DESTDIR)@prefix@\nexec_prefix=@exec_prefix@\nlibdir=@libdir@\nincludedir=@includedir@\n\nName: libseafile\nDescription"
},
{
"path": "lib/net.c",
"chars": 17472,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n#ifdef WIN32\n #define WINVER 0x0501\n "
},
{
"path": "lib/net.h",
"chars": 2362,
"preview": "\n#ifndef CCNET_NET_H\n#define CCNET_NET_H\n\n#ifdef WIN32\n #include <inttypes.h>\n #include <winsock2.h>\n #include "
},
{
"path": "lib/repo.vala",
"chars": 6661,
"preview": "namespace Seafile {\n\npublic class Repo : Object {\n\n // Section 1: Basic information\n // Members in this section sh"
},
{
"path": "lib/rpc_table.py",
"chars": 5933,
"preview": "\"\"\"\nDefine RPC functions needed to generate\n\"\"\"\n\n# [ <ret-type>, [<arg_types>] ]\nfunc_table = [\n [ \"int\", [] ],\n ["
},
{
"path": "lib/seahub.vala",
"chars": 244,
"preview": "namespace Seafile {\n\npublic class ShareLinkInfo : Object {\n public string repo_id { set; get; }\n public stri"
},
{
"path": "lib/search-result.vala",
"chars": 376,
"preview": "// compile this file with `valac --pkg posix repo.vala -C -H repo.h`\n\nnamespace Seafile {\n\npublic class SearchResult: Ob"
},
{
"path": "lib/task.vala",
"chars": 1353,
"preview": "namespace Seafile {\n\npublic class Task : Object {\n\n\tpublic char _tx_id[37];\n\tpublic string tx_id {\n\t\tget { return (strin"
},
{
"path": "lib/timer.c",
"chars": 1641,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#if defined(__FreeBSD__) || defined(__Net"
},
{
"path": "lib/timer.h",
"chars": 769,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#ifndef CCNET_TIMER_H\n#define CCNET_TIMER"
},
{
"path": "lib/utils.c",
"chars": 57925,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#include <config.h>\n\n#include \"common.h\"\n"
},
{
"path": "lib/utils.h",
"chars": 10240,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#ifndef CCNET_UTILS_H\n#define CCNET_UTILS"
},
{
"path": "lib/webaccess.vala",
"chars": 227,
"preview": "namespace Seafile {\n\npublic class WebAccess : Object {\n public string repo_id { set; get; }\n public string o"
},
{
"path": "m4/ax_lib_sqlite3.m4",
"chars": 5001,
"preview": "# ===========================================================================\n# http://www.nongnu.org/autoconf-a"
},
{
"path": "m4/glib-gettext.m4",
"chars": 12541,
"preview": "# Copyright (C) 1995-2002 Free Software Foundation, Inc.\n# Copyright (C) 2001-2003,2004 Red Hat, Inc.\n#\n# This file is f"
},
{
"path": "m4/python.m4",
"chars": 1932,
"preview": "## this one is commonly used with AM_PATH_PYTHONDIR ...\ndnl AM_CHECK_PYMOD(MODNAME [,SYMBOL [,ACTION-IF-FOUND [,ACTION-I"
},
{
"path": "notification-server/.golangci.yml",
"chars": 159,
"preview": "run:\n timeout: 2m\n\nlinters:\n enable:\n - govet\n - gocyclo\n - gosimple\n - ineffassign\n - staticcheck\n - unus"
},
{
"path": "notification-server/ccnet.conf",
"chars": 108,
"preview": "[Database]\nENGINE = mysql\nHOST = 127.0.0.1\nUSER = seafile\nPASSWD = seafile\nDB = ccnet-db\nCREATE_TABLES=true\n"
},
{
"path": "notification-server/client.go",
"chars": 6545,
"preview": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"runtime/debug\"\n\t\"time\"\n\n\tjwt \"github.com/golang-jwt/jwt/v5\"\n\t\"github.co"
},
{
"path": "notification-server/dup2.go",
"chars": 131,
"preview": "//go:build !(linux && arm64)\n\npackage main\n\nimport (\n\t\"syscall\"\n)\n\nfunc Dup(from, to int) error {\n\treturn syscall.Dup2(f"
},
{
"path": "notification-server/dup3.go",
"chars": 131,
"preview": "//go:build linux && arm64\n\npackage main\n\nimport (\n\t\"syscall\"\n)\n\nfunc Dup(from, to int) error {\n\treturn syscall.Dup3(from"
},
{
"path": "notification-server/event.go",
"chars": 4035,
"preview": "package main\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"reflect\"\n\t\"runtime/debug\"\n\t\"time\"\n\n\tlog \"github.com/sirupsen/logrus"
},
{
"path": "notification-server/go.mod",
"chars": 491,
"preview": "module github.com/haiwen/seafile-server/notification-server\n\ngo 1.17\n\nrequire (\n\tgithub.com/dgraph-io/ristretto v0.2.0\n\t"
},
{
"path": "notification-server/go.sum",
"chars": 3549,
"preview": "github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=\ngithub.com/cespare/xxhash/v2 v2.1.1/"
},
{
"path": "notification-server/logger.go",
"chars": 782,
"preview": "package main\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\n\tlog \"github.com/sirupsen/logrus\"\n)\n\nconst (\n\ttimestampFormat = \"[2006-01-02 1"
},
{
"path": "notification-server/server.go",
"chars": 8695,
"preview": "package main\n\nimport (\n\t\"database/sql\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n\t\"os/signal\"\n\t\"path/filep"
},
{
"path": "notification-server/subscriptions.go",
"chars": 2793,
"preview": "package main\n\nimport (\n\t\"sync\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"github.com/dgraph-io/ristretto/z\"\n\t\"github.com/gorilla/websocke"
},
{
"path": "pytest.ini",
"chars": 144,
"preview": "[pytest]\naddopts = -vv -s\nlog_format = %(asctime)s:%(name)s:%(levelname)s:%(message)s\nlog_date_format = %Y-%m-%d %H:%M:%"
},
{
"path": "python/LICENSE.txt",
"chars": 11358,
"preview": "\n Apache License\n Version 2.0, January 2004\n "
},
{
"path": "python/Makefile.am",
"chars": 26,
"preview": "SUBDIRS = seafile seaserv\n"
},
{
"path": "python/seafile/Makefile.am",
"chars": 75,
"preview": "seafiledir=${pyexecdir}/seafile\n\nseafile_PYTHON = __init__.py rpcclient.py\n"
},
{
"path": "python/seafile/__init__.py",
"chars": 135,
"preview": "from .rpcclient import SeafServerThreadedRpcClient as ServerThreadedRpcClient\n\nclass TaskType(object):\n DOWNLOAD = 0\n"
},
{
"path": "python/seafile/rpcclient.py",
"chars": 33968,
"preview": "from pysearpc import searpc_func, SearpcError, NamedPipeClient\n\nclass SeafServerThreadedRpcClient(NamedPipeClient):\n\n "
},
{
"path": "python/seaserv/Makefile.am",
"chars": 80,
"preview": "seaservdir=${pyexecdir}/seaserv\n\nseaserv_PYTHON = __init__.py service.py api.py\n"
},
{
"path": "python/seaserv/__init__.py",
"chars": 2274,
"preview": "from . import service\nfrom .service import seafserv_threaded_rpc, ccnet_threaded_rpc\nfrom .service import send_command, "
},
{
"path": "python/seaserv/api.py",
"chars": 48623,
"preview": "from .service import seafserv_threaded_rpc, ccnet_threaded_rpc\nfrom pysearpc import SearpcError\nimport json\n\n\"\"\"\nGeneral"
},
{
"path": "python/seaserv/service.py",
"chars": 25787,
"preview": "from datetime import datetime\nimport json\nimport logging\nimport os\nimport sys\nimport configparser\nfrom urllib.parse impo"
},
{
"path": "run_tests.sh",
"chars": 165,
"preview": "#!/bin/bash\n\nset -e\n\nSCRIPT=${BASH_SOURCE[0]}\nPROJECT_DIR=$(dirname \"${SCRIPT}\")\n\ncd $PROJECT_DIR\n\nexport PYTHONPATH=$PR"
},
{
"path": "scripts/Makefile.am",
"chars": 66,
"preview": "bin_SCRIPTS = parse_seahub_db.py\n\nEXTRA_DIST = parse_seahub_db.py\n"
},
{
"path": "scripts/parse_seahub_db.py",
"chars": 113,
"preview": "import json\nimport seahub_settings\n\ndb_infos = seahub_settings.DATABASES['default']\n\nprint(json.dumps(db_infos))\n"
},
{
"path": "scripts/sql/mysql/ccnet.sql",
"chars": 2948,
"preview": "CREATE TABLE IF NOT EXISTS Binding (\n id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,\n email VARCHAR(255),\n peer_id CH"
},
{
"path": "scripts/sql/mysql/seafile.sql",
"chars": 9454,
"preview": "CREATE TABLE IF NOT EXISTS Branch (\n id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,\n name VARCHAR(10),\n repo_id CHAR("
},
{
"path": "scripts/sql/sqlite/config.sql",
"chars": 70,
"preview": "CREATE TABLE IF NOT EXISTS Config (key TEXT PRIMARY KEY, value TEXT);\n"
},
{
"path": "scripts/sql/sqlite/groupmgr.sql",
"chars": 655,
"preview": "CREATE TABLE IF NOT EXISTS `Group` (`group_id` INTEGER PRIMARY KEY AUTOINCREMENT, `group_name` VARCHAR(255), `creator_na"
},
{
"path": "scripts/sql/sqlite/org.sql",
"chars": 613,
"preview": "CREATE TABLE IF NOT EXISTS OrgGroup (org_id INTEGER, group_id INTEGER);\nCREATE INDEX IF NOT EXISTS groupid_indx on OrgGr"
},
{
"path": "scripts/sql/sqlite/seafile.sql",
"chars": 6245,
"preview": "CREATE TABLE IF NOT EXISTS Branch (name VARCHAR(10), repo_id CHAR(40), commit_id CHAR(40), PRIMARY KEY (repo_id, name));"
},
{
"path": "scripts/sql/sqlite/user.sql",
"chars": 1244,
"preview": "CREATE TABLE IF NOT EXISTS Binding (email TEXT, peer_id TEXT);\nCREATE UNIQUE INDEX IF NOT EXISTS peer_index on Binding ("
},
{
"path": "server/Makefile.am",
"chars": 2290,
"preview": "SUBDIRS = gc\n\nAM_CFLAGS = -DPKGDATADIR=\\\"$(pkgdatadir)\\\" \\\n\t-DPACKAGE_DATA_DIR=\\\"\"$(pkgdatadir)\"\\\" \\\n\t-DSEAFILE_SERVER \\"
},
{
"path": "server/access-file.c",
"chars": 71712,
"preview": "#include \"common.h\"\n\n#ifdef HAVE_EVHTP\n#define DEBUG_FLAG SEAFILE_DEBUG_HTTP\n#include \"log.h\"\n\n#if defined(__FreeBSD__) "
},
{
"path": "server/access-file.h",
"chars": 115,
"preview": "#ifndef ACCESS_FILE_H\n#define ACCESS_FILE_H\n\n#ifdef HAVE_EVHTP\nint\naccess_file_init (evhtp_t *htp);\n#endif\n\n#endif\n"
},
{
"path": "server/change-set.c",
"chars": 10358,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#include \"common.h\"\n\n#include \"seafile-se"
},
{
"path": "server/change-set.h",
"chars": 829,
"preview": "/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */\n\n#ifndef SEAF_CHANGE_SET_H\n#define SEAF_CH"
},
{
"path": "server/copy-mgr.c",
"chars": 5276,
"preview": "#include \"common.h\"\n#include \"log.h\"\n\n#include <pthread.h>\n\n#include \"seafile-session.h\"\n#include \"seafile-object.h\"\n#in"
}
]
// ... and 84 more files (download for full content)
About this extraction
This page contains the full source code of the haiwen/seafile-server GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 284 files (2.8 MB), approximately 748.8k tokens, and a symbol index with 3546 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.