├── .github └── workflows │ ├── build.yml │ ├── docker-deploy.yml │ └── macos-pkg.yml ├── .gitignore ├── .gitmodules ├── COPYRIGHT ├── Dockerfile ├── EXCLUDE ├── Makefile.in ├── OS_X ├── License.rtf ├── ReadMe.rtf ├── Welcome.rtf ├── background.tiff └── distribution.xml ├── README.md ├── SPEC ├── VERSION ├── aclocal.m4 ├── applefile.c ├── applefile.h ├── argcargv.c ├── argcargv.h ├── base64.c ├── base64.h ├── bootstrap.sh ├── ca.sh ├── cksum.c ├── cksum.h ├── code.c ├── code.h ├── command.c ├── command.h ├── config.guess ├── config.h.in ├── config.sub ├── configure.ac ├── connect.c ├── connect.h ├── contrib ├── fsspy.c └── specialist ├── daemon.c ├── docker-compose.yml ├── docker ├── entrypoint └── etc │ ├── rsyslog.d │ ├── imux.conf │ └── stdout.conf │ └── rsyslogd.conf ├── fsdiff.c ├── hardlink.c ├── install-sh ├── ktcheck.c ├── lapply.c ├── largefile.h ├── lcksum.c ├── lcreate.c ├── lfdiff.c ├── list.c ├── list.h ├── llist.c ├── llist.h ├── lmerge.c ├── lmerge.h ├── logname.c ├── logname.h ├── lsize.c ├── lsort.c ├── man ├── applefile.5 ├── fsdiff.1 ├── ktcheck.1 ├── lapply.1 ├── lcksum.1 ├── lcreate.1 ├── lfdiff.1 ├── lmerge.1 ├── lsort.1 ├── radmind.8 ├── rash.1 ├── repo.1 └── twhich.1 ├── mkdirs.c ├── mkdirs.h ├── mkprefix.c ├── mkprefix.h ├── openssl_compat.c ├── openssl_compat.h ├── pathcmp.c ├── pathcmp.h ├── progress.c ├── progress.h ├── ra.sh ├── radstat.c ├── radstat.h ├── repo.c ├── report.c ├── report.h ├── retr.c ├── rmdirs.c ├── rmdirs.h ├── root.c ├── root.h ├── stor.c ├── t2pkg.c ├── tls.c ├── tls.h ├── transcript.c ├── transcript.h ├── twhich.c ├── update.c ├── update.h ├── version.c ├── wildcard.c └── wildcard.h /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: 3 | push: 4 | branches: [ master ] 5 | pull_request: 6 | branches: [ master ] 7 | jobs: 8 | build: 9 | strategy: 10 | matrix: 11 | os: [ ubuntu-18.04, ubuntu-20.04, macos-10.15, macos-11 ] 12 | name: ${{ matrix.os }} radmind 13 | runs-on: ${{ matrix.os }} 14 | 15 | steps: 16 | - name: Checkout sources 17 | uses: actions/checkout@v2 18 | - name: Configure 19 | run: | 20 | if [ "$RUNNER_OS" == "macOS" ]; then 21 | brew install openssl 22 | sudo ln -s /usr/local/opt/openssl /usr/local/openssl 23 | fi 24 | sh bootstrap.sh 25 | ./configure 26 | - name: Build 27 | run: | 28 | make 29 | - name: Install 30 | run: | 31 | sudo make install 32 | - name: Test 33 | run: | 34 | fsdiff -c sha1 -K /dev/null . 35 | 36 | -------------------------------------------------------------------------------- /.github/workflows/docker-deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy docker 2 | on: 3 | workflow_dispatch 4 | env: 5 | REGISTRY: ghcr.io 6 | IMAGE_NAME: ${{ github.repository }} 7 | jobs: 8 | build-and-push-image: 9 | runs-on: ubuntu-latest 10 | permissions: 11 | contents: read 12 | packages: write 13 | steps: 14 | - name: Check Out Repo 15 | uses: actions/checkout@v2 16 | - name: Extract metadata (tags, labels) for Docker 17 | id: meta 18 | uses: docker/metadata-action@v3 19 | with: 20 | images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} 21 | - name: Login 22 | uses: docker/login-action@v1 23 | with: 24 | registry: ${{ env.REGISTRY }} 25 | username: ${{ github.actor }} 26 | password: ${{ secrets.GITHUB_TOKEN }} 27 | - name: Set up QEMU 28 | uses: docker/setup-qemu-action@v1 29 | - name: Set up Docker Buildx 30 | id: buildx 31 | uses: docker/setup-buildx-action@v1 32 | - name: Cache docker layers 33 | uses: actions/cache@v2 34 | with: 35 | path: /tmp/.buildx-cache 36 | key: ${{ runner.os }}-buildx-${{ github.sha }} 37 | restore-keys: | 38 | ${{ runner.os }}-buildx- 39 | - name: Build and push 40 | id: docker_build 41 | uses: docker/build-push-action@v2 42 | with: 43 | context: . 44 | builder: ${{ steps.buildx.outputs.name }} 45 | platforms: linux/amd64,linux/arm64 46 | push: true 47 | tags: 1.14.1a 48 | labels: ${{ steps.meta.outputs.labels }} 49 | cache-from: type=local,src=/tmp/.buildx-cache 50 | cache-to: type=local,dest=/tmp/.buildx-cache 51 | - name: Image digest 52 | run: echo ${{ steps.docker_build.outputs.digest }} 53 | -------------------------------------------------------------------------------- /.github/workflows/macos-pkg.yml: -------------------------------------------------------------------------------- 1 | name: Build Pkg 2 | on: 3 | workflow_dispatch 4 | jobs: 5 | build-pkg: 6 | strategy: 7 | matrix: 8 | os: [ macos-10.15 ] 9 | name: ${{ matrix.os }} radmind 10 | runs-on: ${{ matrix.os }} 11 | steps: 12 | - name: Checkout sources 13 | uses: actions/checkout@v2 14 | - name: Configure 15 | run: | 16 | if [ "$RUNNER_OS" == "macOS" ]; then 17 | brew install openssl 18 | sudo ln -s /usr/local/opt/openssl /usr/local/openssl 19 | fi 20 | sh bootstrap.sh 21 | ./configure 22 | - name: make package 23 | run: | 24 | make package 25 | - name: Upload to GitHub Release 26 | uses: svenstaro/upload-release-action@v2 27 | with: 28 | repo_token: ${{ secrets.GITHUB_TOKEN }} 29 | file: "../RadmindTools-*.pkg" 30 | file_glob: true 31 | tag: ${{ github.ref }} 32 | overwrite: true 33 | asset_name: RadmindTools.pkg 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Autoconf Generated Files # 2 | ############################ 3 | autom4te.cache 4 | configure 5 | 6 | # Configure Generated Files # 7 | ############################# 8 | Makefile 9 | config.h 10 | config.log 11 | config.status 12 | 13 | # Compiled Files # 14 | ################## 15 | *.o 16 | fsdiff 17 | ktcheck 18 | lapply 19 | lcksum 20 | lcreate 21 | lfdiff 22 | lmerge 23 | lsort 24 | radmind 25 | repo 26 | twhich 27 | 28 | # macOS garbage # 29 | ################# 30 | .DS_Store 31 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libsnet"] 2 | path = libsnet 3 | url = git://libsnet.git.sourceforge.net/gitroot/libsnet/libsnet 4 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2003 Regents of The University of Michigan. 2 | All Rights Reserved. 3 | 4 | Permission to use, copy, modify, and distribute this software and 5 | its documentation for any purpose and without fee is hereby granted, 6 | provided that the above copyright notice appears in all copies and 7 | that both that copyright notice and this permission notice appear 8 | in supporting documentation, and that the name of The University 9 | of Michigan not be used in advertising or publicity pertaining to 10 | distribution of the software without specific, written prior 11 | permission. This software is supplied as is without expressed or 12 | implied warranties of any kind. 13 | 14 | Research Systems Unix Group 15 | The University of Michigan 16 | c/o Wesley Craig 17 | 4251 Plymouth Road B1F2, #2600 18 | Ann Arbor, MI 48105-2785 19 | radmind@umich.edu 20 | http://rsug.itd.umich.edu/software/radmind/ 21 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:latest AS builder 2 | 3 | RUN apt-get update && \ 4 | apt-get install -q -y \ 5 | autoconf \ 6 | git \ 7 | gcc \ 8 | libssl-dev \ 9 | make \ 10 | wget 11 | 12 | COPY . /radmind/ 13 | COPY ./.git /radmind/.git/ 14 | COPY ./.gitmodules /radmind/ 15 | 16 | RUN cd radmind && \ 17 | if [ -e radmind ]; then rm -r radmind; fi && \ 18 | sh bootstrap.sh && \ 19 | wget -O config.sub 'https://git.savannah.gnu.org/cgit/config.git/plain/config.sub' && \ 20 | wget -O config.guess 'https://git.savannah.gnu.org/cgit/config.git/plain/config.guess' && \ 21 | cp config.guess libsnet && \ 22 | cp config.sub libsnet && \ 23 | autoconf && \ 24 | cd libsnet && \ 25 | autoconf && \ 26 | cd .. && \ 27 | ./configure && \ 28 | make && \ 29 | make install && \ 30 | mkdir -p /var/radmind/{cert,client,postapply,preapply} 31 | 32 | # Build rsyslog so we can grab omstdout.so 33 | 34 | RUN wget https://www.rsyslog.com/files/download/rsyslog/rsyslog-8.2112.0.tar.gz && \ 35 | tar xzf rsyslog-8.2112.0.tar.gz && \ 36 | cd rsyslog-8.2112.0 && \ 37 | ln -snf /usr/share/zoneinfo/Europe/London /etc/localtime && echo Europe/London > /etc/timezone && \ 38 | apt install -q -y \ 39 | libcurl4-gnutls-dev \ 40 | libestr-dev \ 41 | libfastjson-dev \ 42 | libgcrypt-dev \ 43 | pkg-config \ 44 | uuid-dev \ 45 | zlib1g-dev && \ 46 | ./configure --prefix=/usr --enable-omstdout && \ 47 | make && \ 48 | make install 49 | 50 | FROM ubuntu:latest 51 | 52 | RUN apt-get update && \ 53 | apt-get install -y \ 54 | libssl-dev 55 | 56 | # Add rsyslog (because radmind doesn't log to stdout but rsyslog can w/ omstdout) 57 | 58 | COPY ./docker/etc /etc/ 59 | COPY --from=builder /usr/lib/rsyslog/omstdout.so /usr/local/lib/omstdout.so 60 | RUN apt-get install -y rsyslog && \ 61 | mv /usr/local/lib/omstdout.so /lib/*-linux-gnu/rsyslog/ && \ 62 | rm /etc/rsyslog.d/50-default.conf 63 | 64 | 65 | # Copy radmind 66 | 67 | COPY --from=builder /usr/local/ /usr/local/ 68 | COPY docker/entrypoint /usr/local/bin/entrypoint 69 | 70 | ENTRYPOINT ["/usr/local/bin/entrypoint"] 71 | -------------------------------------------------------------------------------- /EXCLUDE: -------------------------------------------------------------------------------- 1 | EXCLUDE 2 | .git 3 | CVS 4 | Makefile 5 | autom4te.cache 6 | config.log 7 | config.status 8 | -------------------------------------------------------------------------------- /OS_X/License.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf420 2 | {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica;} 3 | {\colortbl;\red255\green255\blue255;} 4 | {\info 5 | {\title Copyright (c) 2003 Regents of The University of Michigan} 6 | {\author Patrick McNeal} 7 | {\*\company University of Michigan}}\margl359\margr359\vieww9000\viewh8400\viewkind0 8 | \deftab720 9 | \pard\pardeftab720\ql\qnatural 10 | 11 | \f0\b\fs24 \cf0 Copyright (c) 2003, 2007 Regents of The University of Michigan\ 12 | All Rights Reserved 13 | \f1\b0 \ 14 | \ 15 | Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appears in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of The University of Michigan not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. This software is supplied as is without expressed or implied warranties of any kind.\ 16 | \ 17 | Research Systems Unix Group\ 18 | The University of Michigan\ 19 | c/o Wesley Craig\ 20 | 4251 Plymouth Road B1F2, #2600\ 21 | Ann Arbor, MI 48105-2785\ 22 | radmind@umich.edu\ 23 | http://radmind.org} -------------------------------------------------------------------------------- /OS_X/ReadMe.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf420 2 | {\fonttbl\f0\fswiss\fcharset77 Helvetica-Bold;\f1\fswiss\fcharset77 Helvetica;} 3 | {\colortbl;\red255\green255\blue255;} 4 | \vieww8640\viewh9000\viewkind0 5 | \pard\ql\qnatural 6 | 7 | \f0\b\fs24 \cf0 About radmind 8 | \f1\b0 \ 9 | Radmind is a set of tools that can be used to maintain systems and act as a tripwire for security purposes.\ 10 | \ 11 | 12 | \f0\b Change Log 13 | \f1\b0 \ 14 | To see what has been changed in the version see the release notes on the Radmind SourceForge site https://sourceforge.net/projects/radmind/ .\ 15 | \ 16 | 17 | \f0\b Requirements\ 18 | 19 | \f1\b0 This package require a Macintosh running Mac OS X 10.3 or later. To run radmind on prior versions of Mac OS X, you must download and build the source code.\ 20 | \ 21 | 22 | \f0\b Installing Radmind 23 | \f1\b0 \ 24 | This package installs software into standard file locations. If you have moved /usr/local/bin, /usr/local/sbin, /usr/local/man or /private/var we recommend that you install from the source code rather than using this installer.\ 25 | \ 26 | You will need administrator privileges to install radmind. This installer installs all components of the radmind tools. To install the server startup item, you will need to run the Radmind Assistant, choose Run Setup Steps from the Session menu, and choose "I'm new, and I'd like to set up a radmind server" in the window.\ 27 | \ 28 | 29 | \f0\b Known Issues 30 | \f1\b0 \ 31 | On OpenDarwin based systems, the message "hfs_bwrite: called with lock bit set" is logged when you are doing a high volume of writes to a volume.\ 32 | \ 33 | 34 | \f0\b Reporting Bugs\ 35 | 36 | \f1\b0 Before submitting a bug report, check the Radmind bug tracker at https://sourceforge.net/tracker/?group_id=141444&atid=749492 to see if it has already been reported. If not, you can submit a detailed report. Include the version of the tools, the version of the OS, the version of the Radmind Assistant, any error messages or crashlogs created by the tools, and a list of the steps it takes to cause the bug.\ 37 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural 38 | \cf0 \ 39 | \pard\ql\qnatural 40 | 41 | \f0\b \cf0 For more information\ 42 | 43 | \f1\b0 For help using any of the radmind tools, see their man page. There is also an active archived mailing list. For more details, see the radmind website's Contact page: http://radmind.org/contact.html\ 44 | \ 45 | Visit the radmind web site at http://radmind.org\ 46 | \ 47 | Copyright (c) 2003, 2007 Regents of The University of Michigan\ 48 | All Rights Reserved} -------------------------------------------------------------------------------- /OS_X/Welcome.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\mac\ansicpg10000\cocoartf102 2 | {\fonttbl\f0\fswiss\fcharset77 Helvetica;} 3 | {\colortbl;\red255\green255\blue255;} 4 | \vieww9000\viewh9000\viewkind0 5 | \pard\qc 6 | 7 | \f0\fs36 \cf0 Welcome to the Radmind tool installer. You will be guided through the necessary steps. 8 | \fs24 \ 9 | } -------------------------------------------------------------------------------- /OS_X/background.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Radmind/radmind/e30841e7de583e5c5412673ede5099399a4b501a/OS_X/background.tiff -------------------------------------------------------------------------------- /OS_X/distribution.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 19 | 20 | 21 | RadmindTools.pkg 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Radmind 2 | ======= 3 | 4 | Radmind is a suite of Unix command-line tools and a server designed to remotely administer the file systems of multiple Unix machines. 5 | 6 | Copyright (c) 2003 Regents of The University of Michigan. 7 | All Rights Reserved. See COPYRIGHT. 8 | 9 | ## Contents 10 | 11 | * [Quick Installation Instructions](#quick-installation-instructions) 12 | * [Detailed Installation Instructions](#detailed-installation-instructions) 13 | * [Configuring for Ubuntu 18.04](#configuring-for-ubuntu-1804) 14 | * [Configuring for CentOS 7](#configuring-for-centos-7) 15 | * [Configuring for FreeBSD 11](#configuring-for-freebsd-11) 16 | * [Configuring for RedHat 9](#configuring-for-redhat-9) 17 | * [Configuring for macOS](#configuring-for-macOS) 18 | * [Getting the Source](#getting-the-source) 19 | * [Configuring and Building](#configuring-and-building) 20 | * [Building an OS X Installer Package](#building-an-os-x-installer-package) 21 | * [Known Issues](#known-issues) 22 | * [More Information](#more-informatino) 23 | * [References](#references) 24 | 25 | ## Quick Installation Instructions 26 | 27 | From within the source directory: 28 | 29 | ``` 30 | ./configure 31 | make 32 | make install 33 | ``` 34 | 35 | ## Detailed Installation Instructions 36 | 37 | ### Configuring for Ubuntu 18.04 38 | 39 | These are the commands I had to run to get radmind to build using Vagrant and [generic/ubuntu1804](https://app.vagrantup.com/generic/boxes/ubuntu1804). 40 | 41 | ``` 42 | sudo apt-get -y update 43 | sudo apt-get -y install gcc 44 | sudo apt-get -y install libssl-dev 45 | sudo apt-get -y install make 46 | sudo apt-get -y install autoconf 47 | 48 | ``` 49 | 50 | ### Configuring for CentOS 7 51 | 52 | These are the commands I had to run to get radmind to build using Vagrant and [generic/centos7](https://app.vagrantup.com/generic/boxes/centos7). 53 | 54 | ``` 55 | sudo yum -y update 56 | sudo yum -y install git 57 | sudo yum -y install openssl-devel.x86_64 58 | ``` 59 | 60 | ### Configuring for FreeBSD 11 61 | 62 | These are the commands I had to run to get radmind to build using Vagrant and [generic/freebsd11](https://app.vagrantup.com/generic/boxes/freebsd11). 63 | 64 | ``` 65 | sudo pkg update 66 | sudo pkg install -y git 67 | sudo pkg install -y autoconf 68 | ``` 69 | 70 | ### Configuring for RedHat 9 71 | 72 | To properly build Radmind on RedHat 9 with SSL support, you have to specify the location of your Kerberos files: 73 | 74 | ``` 75 | export CPPFLAGS=-I/usr/kerberos/include 76 | ``` 77 | 78 | ### Configuring for macOS 79 | 80 | Last tested on 10.14 (using homebrew) 81 | 82 | - Install [Xcode](https://developer.apple.com/xcode/). 83 | - Install [brew](https://brew.sh). 84 | 85 | Run these commands as an admin user. 86 | 87 | ``` 88 | brew install autoconf 89 | brew install openssl 90 | sudo ln -s /usr/local/opt/openssl /usr/local/openssl 91 | ``` 92 | 93 | Last tested on 10.14 (using fink) 94 | 95 | - Install [Xcode](https://developer.apple.com/xcode/). 96 | - Install [fink](https://finkproject.org). 97 | 98 | Run these commands as an admin user. 99 | 100 | ``` 101 | fink install autoconf 102 | fink install openssl 103 | ``` 104 | 105 | ### Configuring for Raspbian Stretch (Debian 9) 106 | 107 | ``` 108 | sudo apt-get -y update 109 | sudo apt-get -y install git 110 | sudo apt-get -y install autoconf 111 | sudo apt-get -y install libssl-dev 112 | ``` 113 | 114 | ### Getting the Source 115 | 116 | You can either download the source from the [Radmind project homepage](http://radmind.org/) and uncompress it into a directory of your choice, or else you can use git to build the most recent development source of the project. 117 | 118 | Building Radmind from the git repository is a good way to ensure you've got the most up-to-date version of everything. You can also help contribute by filing bug reports on the [Radmind GitHub page](https://github.com/Radmind/radmind). 119 | 120 | First clone the repository locally: 121 | 122 | ``` 123 | git clone https://github.com/Radmind/radmind.git radmind 124 | ``` 125 | 126 | Then move into the directory and check out the required submodules [1]: 127 | 128 | ``` 129 | cd radmind 130 | sh bootstrap.sh 131 | ``` 132 | 133 | ### Configuring and Building 134 | If configure files are to be rebuilt (because we installed it), issue the following commands 135 | ``` 136 | autoconf 137 | cd libsnet 138 | autoconf 139 | cd .. 140 | ``` 141 | 142 | Now that everything is set up, we have to actually do the configuration and installation. Configure the build: 143 | 144 | ``` 145 | ./configure 146 | ``` 147 | 148 | Note that the configure scripts take several options. To see them all, do `./configure --help`. 149 | 150 | Now we're ready to actually build everything together: 151 | 152 | ``` 153 | make 154 | make install 155 | ``` 156 | 157 | ## Building an OS X Installer Package 158 | 159 | The Radmind Makefile contains a target called `package`, which will construct a Mac OS X installer package suitable for distribution. To make the package, log in as an administrator, enter the Radmind source directory, and follow the steps below: 160 | 161 | ``` 162 | ./configure 163 | make package 164 | ``` 165 | 166 | During the build process, you will be prompted for your password. 167 | 168 | PackageMaker currently does not work with `make`, so at the end of the build process you will see "make: *** [package] Error 2" even though that package was created successfully. 169 | 170 | After the source has been built and the package created, you will be left with a package called 'RadmindTools.pkg' in the parent directory of the Radmind source. This file may be double-clicked in the Finder to launch the Installer. 171 | 172 | This target will fail if it is used on a system other than Mac OS X. 173 | 174 | ## Known Issues 175 | 176 | * On OpenDarwin based systems, the message "hfs_bwrite: called with lock bit set" is logged when you are doing a high volume of writes to a volume. 177 | * `lcksum`'s progress output currently does not provide steady feedback increments. 178 | 179 | ## More Information 180 | 181 | If you have any problems with this source, you may want to check [the issue tracker](../../issues) to see if any problems have reports. You can also contact the Radmind development team by e-mailing [mlib-its-mac-github-radmind@lists.utah.edu](mailto:mlib-its-mac-github-radmind@lists.utah.edu) 182 | 183 | An archived e-mail discussion list has also been set up. See the website for details on how to join. 184 | 185 | In June of 2015, management of this project was transferred from the University of Michigan to the University of Utah. The University of Utah decided to migrate the project from the rapidly-deteriorating SourceForge hosting site over to GitHub. We felt that this would help keep the project alive and make it easier to maintain. Note that the University of Utah, while longtime users of Radmind, are no longer contributing to the upkeep of the project except to merge pull requests, make sure it builds, and keep this readme updated. If you feel you would be a better steward for Radmind's future, contact us. 186 | 187 | The transfer of issues/bugs and their comments was automated using the [gosf2github](https://github.com/cmungall/gosf2github) script. Because no username map was readily available, all of the issues and comments were automatically assigned to the member of the University of Utah's team who managed the migration, [@pdarragh](https://github.com/pdarragh). 188 | 189 | ## References 190 | 191 | [1]: Current submodules: 192 | * [libsnet](http://sourceforge.net/projects/libsnet), a networking library with TLS support 193 | -------------------------------------------------------------------------------- /SPEC: -------------------------------------------------------------------------------- 1 | Copyright (c) 2003 Regents of The University of Michigan. 2 | All Rights Reserved. See COPYRIGHT. 3 | 4 | Response codes of x0x are for general commands, e.g. QUIT, NOOP. x3x 5 | are for STAT, x4x are for RETR, x5x for STOR. 6 | 7 | BANNER 8 | 9 | QUIT causes the server to close the connection. 10 | 11 | C: QUIT "\r\n" 12 | S: 201 QUIT OK, closing connection "\r\n" 13 | 14 | NOOP does nothing, but should generate a valid response. 15 | 16 | C: NOOP "\r\n" 17 | S: 202 NOOP OK "\r\n" 18 | 19 | All of STAT, RETR, and STOR take similar arguments. 20 | 21 | ::= "COMMAND" | 22 | "COMMAND" | 23 | "TRANSCRIPT" | 24 | "SPECIAL" | 25 | "FILE" 26 | 27 | ::= encoded ascii blah blah blah 28 | 29 | STAT does not allow a "FILE" . 30 | 31 | C: STAT "\r\n" 32 | S: 230 Returning STAT information "\r\n" 33 | S: f "\r\n" 34 | 35 | RETR 36 | 37 | C: RETR "\r\n" 38 | S: 240 Retrieving file "\r\n" 39 | S: "\r\n" 40 | S: 41 | S: ".\r\n" 42 | 43 | STOR 44 | 45 | C: STOR "\r\n" 46 | S: 350 Storing file "\r\n" 47 | C: "\r\n" 48 | C: 49 | C: ".\r\n" 50 | S: 250 File stored "\r\n" 51 | 52 | AUTH works per rfc2222 SASL. 53 | 54 | COMPress 55 | 56 | C: COMP [optional-data] "\r\n" 57 | S: 320 Ready to start "\r\n" 58 | S: 220 compression [optional-string] enabled "\r\n" 59 | 60 | REPOrt an event on the client 61 | 62 | C: REPO "\r\n" 63 | S: 215 Report successful "\r\n" 64 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | internal 2 | -------------------------------------------------------------------------------- /aclocal.m4: -------------------------------------------------------------------------------- 1 | AC_DEFUN([CHECK_SNET], 2 | [ 3 | AC_MSG_CHECKING(for snet) 4 | snetdir="libsnet" 5 | AC_ARG_WITH(snet, 6 | AC_HELP_STRING([--with-snet=DIR], [path to snet]), 7 | snetdir="$withval") 8 | if test -f "$snetdir/snet.h"; then 9 | found_snet="yes"; 10 | CPPFLAGS="$CPPFLAGS -I$snetdir"; 11 | fi 12 | if test x_$found_snet != x_yes; then 13 | AC_MSG_ERROR(cannot find snet libraries) 14 | else 15 | LIBS="$LIBS -lsnet"; 16 | LDFLAGS="$LDFLAGS -L$snetdir"; 17 | fi 18 | AC_MSG_RESULT(yes) 19 | ]) 20 | 21 | AC_DEFUN([CHECK_SSL], 22 | [ 23 | AC_MSG_CHECKING(for ssl) 24 | ssldirs="/usr/local/openssl /usr/lib/openssl /usr/openssl \ 25 | /usr/local/ssl /usr/lib/ssl /usr/ssl \ 26 | /usr/pkg /usr/local /usr /sw /opt/sw" 27 | AC_ARG_WITH(ssl, 28 | AC_HELP_STRING([--with-ssl=DIR], [path to ssl]), 29 | ssldirs="$withval") 30 | for dir in $ssldirs; do 31 | ssldir="$dir" 32 | if test -f "$dir/include/openssl/ssl.h"; then 33 | found_ssl="yes"; 34 | CPPFLAGS="$CPPFLAGS -I$ssldir/include"; 35 | break; 36 | fi 37 | if test -f "$dir/include/ssl.h"; then 38 | found_ssl="yes"; 39 | CPPFLAGS="$CPPFLAGS -I$ssldir/include"; 40 | break 41 | fi 42 | done 43 | if test x_$found_ssl != x_yes; then 44 | AC_MSG_ERROR(cannot find ssl libraries) 45 | else 46 | AC_DEFINE(HAVE_LIBSSL) 47 | LIBS="$LIBS -lssl -lcrypto"; 48 | LDFLAGS="$LDFLAGS -L$ssldir/lib"; 49 | fi 50 | AC_MSG_RESULT(yes) 51 | ]) 52 | 53 | AC_DEFUN([CHECK_ZLIB], 54 | [ 55 | AC_MSG_CHECKING(for zlib) 56 | zlibdirs="/usr /usr/local /sw /opt/sw" 57 | withval="" 58 | AC_ARG_WITH(zlib, 59 | [AC_HELP_STRING([--with-zlib=DIR], [path to zlib])], 60 | []) 61 | if test x_$withval != x_no; then 62 | if test x_$withval != x_yes -a \! -z "$withval"; then 63 | zlibdirs="$withval" 64 | fi 65 | for dir in $zlibdirs; do 66 | zlibdir="$dir" 67 | if test -f "$dir/include/zlib.h"; then 68 | found_zlib="yes"; 69 | break; 70 | fi 71 | done 72 | if test x_$found_zlib = x_yes; then 73 | if test "$dir" != "/usr"; then 74 | CPPFLAGS="$CPPFLAGS -I$zlibdir/include"; 75 | LDFLAGS="$LDFLAGS -L$zlibdir/lib"; 76 | ac_configure_args="$ac_configure_args --with-zlib=$dir"; 77 | fi 78 | LIBS="$LIBS -lz"; 79 | AC_DEFINE(HAVE_ZLIB) 80 | AC_MSG_RESULT(yes) 81 | else 82 | AC_MSG_RESULT(no) 83 | fi 84 | else 85 | ac_configure_args="$ac_configure_args --with-zlib=no"; 86 | AC_MSG_RESULT(no) 87 | fi 88 | ]) 89 | 90 | AC_DEFUN([SET_NO_SASL], 91 | [ 92 | ac_configure_args="$ac_configure_args --with-sasl=no"; 93 | AC_MSG_RESULT(Disabled SASL) 94 | ]) 95 | 96 | AC_DEFUN([CHECK_UNIVERSAL_BINARIES], 97 | [ 98 | AC_ARG_ENABLE(universal_binaries, 99 | AC_HELP_STRING([--enable-universal-binaries], [build universal binaries (default=no)]), 100 | ,[enable_universal_binaries=no]) 101 | if test "${enable_universal_binaries}" = "yes"; then 102 | case "${host_os}" in 103 | darwin8*) 104 | macosx_sdk="MacOSX10.4u.sdk" 105 | arches="-arch i386 -arch ppc" 106 | ;; 107 | 108 | darwin9*|darwin10*|darwin11*) 109 | dep_target="-mmacosx-version-min=10.4" 110 | macosx_sdk="MacOSX10.5.sdk" 111 | arches="-arch i386 -arch x86_64 -arch ppc -arch ppc64" 112 | LDFLAGS="$LDFLAGS -L/Developer/SDKs/$macosx_sdk/usr/lib" 113 | ;; 114 | 115 | *) 116 | AC_MSG_ERROR([Building universal binaries on ${host_os} is not supported]) 117 | ;; 118 | esac 119 | 120 | echo =========================================================== 121 | echo Setting up universal binaries for ${host_os} 122 | echo =========================================================== 123 | OPTOPTS="$OPTOPTS -isysroot /Developer/SDKs/$macosx_sdk $dep_target $arches" 124 | fi 125 | ]) 126 | 127 | AC_DEFUN([MACOSX_MUTE_DEPRECATION_WARNINGS], 128 | [ 129 | dnl Lion deprecates a system-provided OpenSSL. Build output 130 | dnl is cluttered with useless deprecation warnings. 131 | 132 | AS_IF([test x"$CC" = x"gcc"], [ 133 | case "${host_os}" in 134 | darwin11*) 135 | AC_MSG_NOTICE([muting deprecation warnings from compiler]) 136 | OPTOPTS="$OPTOPTS -Wno-deprecated-declarations" 137 | ;; 138 | 139 | *) 140 | ;; 141 | esac 142 | ]) 143 | ]) 144 | -------------------------------------------------------------------------------- /applefile.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | #include "config.h" 7 | #include "applefile.h" 8 | #include 9 | #include 10 | 11 | #ifdef __APPLE__ 12 | #include 13 | 14 | struct attrlist getalist = { 15 | ATTR_BIT_MAP_COUNT, 16 | 0, 17 | ATTR_CMN_FNDRINFO, 18 | 0, 19 | 0, 20 | ATTR_FILE_RSRCLENGTH, 21 | 0, 22 | }; 23 | 24 | struct attrlist getdiralist = { 25 | ATTR_BIT_MAP_COUNT, 26 | 0, 27 | ATTR_CMN_FNDRINFO, 28 | 0, 29 | 0, 30 | 0, 31 | 0, 32 | }; 33 | 34 | struct attrlist setalist = { 35 | ATTR_BIT_MAP_COUNT, 36 | 0, 37 | ATTR_CMN_FNDRINFO, 38 | 0, 39 | 0, 40 | 0, 41 | 0, 42 | }; 43 | #endif /* __APPLE__ */ 44 | 45 | struct as_header as_header = { 46 | AS_MAGIC, 47 | AS_VERSION, 48 | { 49 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 50 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 51 | }, 52 | AS_NENTRIES, 53 | }; 54 | 55 | extern struct as_header as_header; 56 | 57 | /* endian handlers for x86 Macs */ 58 | void 59 | as_entry_netswap( struct as_entry *e ) 60 | { 61 | #ifdef __BIG_ENDIAN__ 62 | return; 63 | #else /* __BIG_ENDIAN__ */ 64 | e->ae_id = htonl( e->ae_id ); 65 | e->ae_offset = htonl( e->ae_offset ); 66 | e->ae_length = htonl( e->ae_length ); 67 | #endif /* __BIG_ENDIAN__ */ 68 | } 69 | 70 | void 71 | as_entry_hostswap( struct as_entry *e ) 72 | { 73 | #ifdef __BIG_ENDIAN__ 74 | return; 75 | #else /* __BIG_ENDIAN__ */ 76 | e->ae_id = ntohl( e->ae_id ); 77 | e->ae_offset = ntohl( e->ae_offset ); 78 | e->ae_length = ntohl( e->ae_length ); 79 | #endif /* __BIG_ENDIAN__ */ 80 | } 81 | -------------------------------------------------------------------------------- /applefile.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | /* 7 | * applesingle format: 8 | * header: 9 | * -magic number (4 bytes) 10 | * -version number (4 bytes) 11 | * -filler (16 bytes) 12 | * -number of entries (2 bytes) 13 | * -x number of entries, with this format: 14 | * id (4 bytes) 15 | * offset (4 bytes) 16 | * length (4 bytes) 17 | * data: 18 | * -finder info 19 | * -rsrc fork 20 | * -data fork 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #define AS_HEADERLEN 26 28 | 29 | #ifdef __BIG_ENDIAN__ 30 | 31 | #define AS_MAGIC 0x00051600 32 | #define AS_VERSION 0x00020000 33 | #define AS_NENTRIES 0x0003 34 | 35 | #else /* __BIG_ENDIAN__ */ 36 | 37 | #define AS_MAGIC 0x00160500 38 | #define AS_VERSION 0x00000200 39 | #define AS_NENTRIES 0x0300 40 | 41 | #endif /* __BIG_ENDIAN__ */ 42 | 43 | #define ASEID_DFORK 1 44 | #define ASEID_RFORK 2 45 | #define ASEID_FINFO 9 46 | 47 | #define AS_FIE 0 /* for array of ae_entry structs */ 48 | #define AS_RFE 1 49 | #define AS_DFE 2 50 | 51 | #define FINFOLEN 32 52 | 53 | #define FI_CREATOR_OFFSET 4 54 | 55 | /* applesingle entry */ 56 | struct as_entry { 57 | uint32_t ae_id; 58 | uint32_t ae_offset; 59 | uint32_t ae_length; 60 | }; 61 | 62 | /* applesingle header */ 63 | struct as_header { 64 | uint32_t ah_magic; 65 | uint32_t ah_version; 66 | uint8_t ah_filler[ 16 ]; 67 | uint16_t ah_num_entries; 68 | }; 69 | 70 | #if defined(__APPLE__) && defined(__LP64__) && defined(__GNUC__) 71 | #pragma pack(push) 72 | #pragma pack(4) 73 | #endif /* __APPLE__ && __LP64__ && __GNUC__ */ 74 | struct attr_info { 75 | uint32_t ai_size; 76 | uint8_t ai_data[ FINFOLEN ]; 77 | off_t ai_rsrc_len; 78 | }; 79 | #if defined(__APPLE__) && defined(__LP64__) && defined(__GNUC__) 80 | #pragma pack(pop) 81 | #endif /* __APPLE__ && __LP64__ && __GNUC__ */ 82 | 83 | struct applefileinfo { 84 | struct attr_info ai; // finder info 85 | struct as_entry as_ents[ 3 ]; // Apple Single entries 86 | // For Finder info, rcrs and data forks 87 | off_t as_size; // Total apple single file size 88 | }; 89 | 90 | void as_entry_netswap( struct as_entry *e ); 91 | void as_entry_hostswap( struct as_entry *e ); 92 | off_t ckapplefile( char *applefile, int afd ); 93 | -------------------------------------------------------------------------------- /argcargv.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | /* 7 | * Return parsed argc/argv from the net. 8 | */ 9 | 10 | #include "config.h" 11 | 12 | #include 13 | 14 | #include "argcargv.h" 15 | 16 | #define ACV_ARGC 10 17 | #define ACV_WHITE 0 18 | #define ACV_WORD 1 19 | static ACAV *acavg = NULL; 20 | 21 | ACAV* 22 | acav_alloc( void ) 23 | { 24 | ACAV *acav; 25 | 26 | if ( ( acav = (ACAV*)malloc( sizeof( ACAV ) ) ) == NULL ) { 27 | return( NULL ); 28 | } 29 | if ( ( acav->acv_argv = 30 | (char **)malloc( sizeof(char *) * ( ACV_ARGC ) ) ) == NULL ) { 31 | free( acav ); 32 | return( NULL ); 33 | } 34 | acav->acv_argc = ACV_ARGC; 35 | 36 | return( acav ); 37 | } 38 | 39 | /* 40 | * acav->acv_argv = **argv[] if passed an ACAV 41 | */ 42 | 43 | int 44 | acav_parse( ACAV *acav, char *line, char **argv[] ) 45 | { 46 | int ac; 47 | int state; 48 | 49 | if ( acav == NULL ) { 50 | if ( acavg == NULL ) { 51 | if (( acavg = acav_alloc()) == NULL ) { 52 | return( -1 ); 53 | } 54 | } 55 | acav = acavg; 56 | } 57 | 58 | ac = 0; 59 | state = ACV_WHITE; 60 | 61 | for ( ; *line != '\0'; line++ ) { 62 | switch ( *line ) { 63 | case ' ' : 64 | case '\t' : 65 | case '\n' : 66 | if ( state == ACV_WORD ) { 67 | *line = '\0'; 68 | state = ACV_WHITE; 69 | } 70 | break; 71 | default : 72 | if ( state == ACV_WHITE ) { 73 | acav->acv_argv[ ac++ ] = line; 74 | if ( ac >= acav->acv_argc ) { 75 | /* realloc */ 76 | if (( acav->acv_argv = (char **)realloc( acav->acv_argv, 77 | sizeof( char * ) * ( acav->acv_argc + ACV_ARGC ))) 78 | == NULL ) { 79 | return( -1 ); 80 | } 81 | acav->acv_argc += ACV_ARGC; 82 | } 83 | state = ACV_WORD; 84 | } 85 | } 86 | } 87 | 88 | acav->acv_argv[ ac ] = NULL; 89 | *argv = acav->acv_argv; 90 | return( ac ); 91 | } 92 | 93 | int 94 | acav_free( ACAV *acav ) 95 | { 96 | free( acav->acv_argv ); 97 | free( acav ); 98 | 99 | return( 0 ); 100 | } 101 | -------------------------------------------------------------------------------- /argcargv.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | #define argcargv(X, Y) (acav_parse( NULL, X, Y )) 7 | 8 | typedef struct { 9 | int acv_argc; 10 | char **acv_argv; 11 | } ACAV; 12 | ACAV* acav_alloc( void ); 13 | int acav_parse( ACAV *acav, char *, char *** ); 14 | int acav_free( ACAV *acav ); 15 | -------------------------------------------------------------------------------- /base64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | #define SZ_BASE64_E( x ) (((x)+2)/3*4+1) 7 | #define SZ_BASE64_D( x ) (((x)*3)/4) 8 | 9 | void base64_e( unsigned char *, int, char * ); 10 | void base64_d( char *, int, unsigned char * ); 11 | -------------------------------------------------------------------------------- /bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Prepare a checked-out source tree for build 4 | # 5 | # Make sure git and autoconf are in PATH 6 | 7 | # If necessary, populate libsnet/ 8 | if [ -f "./.gitmodules" -a ! -f "./libsnet/.git" ] 9 | then 10 | git submodule init 11 | git submodule update 12 | fi 13 | 14 | (cd libsnet && autoconf) 15 | 16 | autoconf 17 | 18 | exit 0 19 | -------------------------------------------------------------------------------- /ca.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Certificate Authority shell script (cash) 4 | # Basic client side functions include: 5 | # 6 | # trip 7 | # update 8 | # create 9 | # auto 10 | # force 11 | # 12 | 13 | EDITOR=${EDITOR:-vi} 14 | MAILDOMAIN="_RADMIND_MAIL_DOMAIN" 15 | VERSION=_RADMIND_VERSION 16 | RADMINDDIR=/var/radmind 17 | #CADIR=${RADMINDDIR}/ca 18 | CERTDIR=${RADMINDDIR}/cert 19 | SPECIALDIR=${RADMINDDIR}/special 20 | CLIENTCERTDIR=/private/var/radmind/cert 21 | CADIR=./CA 22 | OPENSSLCNF=openssl2.cnf 23 | 24 | PATH=/usr/local/bin:/usr/bin:/bin; export PATH 25 | 26 | MKTEMP="_RADMIND_MKTEMP" 27 | TEMPFILES=FALSE 28 | TMPDIR="/tmp/.ca.$$" 29 | if [ -f "${MKTEMP}" ]; then 30 | TMPDIR=`${MKTEMP} -qd /tmp/.ca.$$.XXXXXX` 31 | if [ $? -ne 0 ]; then 32 | echo "mktemp failed" 33 | exit 1 34 | fi 35 | fi 36 | 37 | makecert() { 38 | if [ -z $1 ]; then 39 | echo -n "Enter new certificate common name: " 40 | read CN 41 | if [ -z ${CN} ]; then 42 | echo "Invalid common name" 43 | cleanup 44 | exit 1 45 | fi 46 | else 47 | CN=$1 48 | fi 49 | CERT=`grep /CN=${CN}/ index.txt | grep ^V | cut -f4` 50 | if [ ! -z ${CERT} ]; then 51 | echo Using existing certificate ${CERT}.pem 52 | return 0 53 | fi 54 | openssl req -new -keyout keys/${CN}.key -out csrs/${CN}.csr -days 360 -config openssl2.cnf -nodes <&2 84 | exit 1 85 | } 86 | 87 | cleanup() { 88 | if [ "$TEMPFILES" = FALSE ]; then 89 | rm -fr "${TMPDIR}" 90 | fi 91 | } 92 | 93 | while getopts V opt; do 94 | case $opt in 95 | V) echo ${VERSION} 96 | exit 0 97 | ;; 98 | 99 | *) usage 100 | ;; 101 | esac 102 | done 103 | shift `expr $OPTIND - 1` 104 | 105 | if [ $# -ne 1 ]; then 106 | usage 107 | fi 108 | 109 | if [ ! -d ${TMPDIR} ]; then 110 | mkdir -m 700 ${TMPDIR} 111 | if [ $? -ne 0 ]; then 112 | echo "Cannot create temporary directory $TMPDIR" 113 | exit 1 114 | fi 115 | fi 116 | 117 | # Trap meaningful signals 118 | trap cleanup HUP INT PIPE QUIT TERM TRAP XCPU XFSZ 119 | echo $1 120 | 121 | case "$1" in 122 | init) 123 | # Setup Certificate Authority 124 | if [ -d ${CADIR} ]; then 125 | echo ${CADIR} already exists 126 | Yn "Remove existing certificate authority?" 127 | if [ $? -eq 0 ]; then 128 | cleanup 129 | exit 1 130 | fi 131 | rm -rf ${CADIR} 132 | if [ $? -ne 0 ]; then 133 | echo "Cannot remove old certificate authority" 134 | cleanup 135 | exit 1 136 | fi 137 | fi 138 | 139 | mkdir -p ${CADIR} 140 | if [ $? -ne 0 ]; then 141 | echo "Cannot create ${CADIR}" 142 | cleanup 143 | exit 1 144 | fi 145 | cd ${CADIR} 146 | if [ $? -ne 0 ]; then 147 | echo "Cannot cd to ${CADIR}" 148 | cleanup 149 | exit 1 150 | fi 151 | mkdir certs private keys csrs 152 | if [ $? -ne 0 ]; then 153 | echo "Cannot create directories" 154 | cleanup 155 | exit 1 156 | fi 157 | echo "01" > serial 158 | touch index.txt 159 | wget http://radmind.org/files/openssl2.cnf 160 | if [ $? -ne 0 ]; then 161 | echo "Cannot get default ${OPENSSLCNF}" 162 | cleanup 163 | exit 1 164 | fi 165 | openssl req -config ${OPENSSLCNF} -x509 -newkey rsa -days 1825 -keyout private/ca-key.pem -out certs/ca-cert.pem -outform PEM 166 | makecert `hostname` 167 | 168 | ;; 169 | 170 | create) 171 | if [ ! -d ${CADIR} ]; then 172 | echo "No certificate authority" 173 | cleanup 174 | exit 1 175 | fi 176 | cd ${CADIR} 177 | 178 | makecert 179 | 180 | cat certs/${CERT}.pem keys/${CN}.key > ${CERTDIR}/${CN}.pem 181 | if [ $? -ne 0 ]; then 182 | echo Unable to create ${CERTDIR}/${CN}.pem 183 | cleanup 184 | exit 1 185 | fi 186 | if [ ! -d ${SPECIALDIR}/${CN}/${CLIENTCERTDIR} ]; then 187 | mkdir -p ${SPECIALDIR}/${CN}/${CLIENTCERTDIR} 188 | if [ $? -ne 0 ]; then 189 | echo Unable to create ${SPECIALDIR}/${CN}/${CLIENTCERTDIR} 190 | cleanup 191 | exit 1 192 | fi 193 | fi 194 | if [ -a ${SPECIALDIR}/${CN}/${CLIENTCERTDIR}/cert.pem ]; then 195 | rm -f ${SPECIALDIR}/${CN}/${CLIENTCERTDIR}/cert.pem 196 | echo Unable to remove old ${SPECIALDIR}/${CN}/${CLIENTCERTDIR}/cert.pem 197 | cleanup 198 | exit 1 199 | fi 200 | 201 | ln -s ${CERTDIR}/${CN}.pem ${SPECIALDIR}/${CN}/${CLIENTCERTDIR}/cert.pem 202 | if [ $? -ne 0 ]; then 203 | echo Unable to link ${CERTDIR}/${CN}.pem to ${SPECIALDIR}/${CN}/${CLIENTCERTDIR}/cert.pem 204 | cleanup 205 | exit 1 206 | fi 207 | ;; 208 | 209 | *) 210 | usage 211 | ;; 212 | 213 | esac 214 | 215 | cleanup 216 | exit 0 217 | -------------------------------------------------------------------------------- /cksum.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #ifdef __APPLE__ 12 | #include 13 | #endif /* __APPLE__ */ 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | 23 | #include "openssl_compat.h" // Compatibility shims for OpenSSL < 1.1.0 24 | #include "applefile.h" 25 | #include "cksum.h" 26 | #include "base64.h" 27 | 28 | /* 29 | * do_cksum calculates the checksum for PATH and returns it base64 encoded 30 | * in cksum_b64 which must be of size SZ_BASE64_E( EVP_MAX_MD_SIZE ). 31 | * 32 | * return values: 33 | * < 0 system error: errno set, no message given 34 | * >= 0 number of bytes check summed 35 | */ 36 | 37 | off_t 38 | do_fcksum( int fd, char *cksum_b64 ) 39 | { 40 | unsigned int md_len; 41 | ssize_t rr; 42 | off_t size = 0; 43 | unsigned char buf[ 8192 ]; 44 | extern EVP_MD *md; 45 | EVP_MD_CTX *mdctx = EVP_MD_CTX_new(); 46 | unsigned char md_value[ SZ_BASE64_D( SZ_BASE64_E( EVP_MAX_MD_SIZE ) ) ]; 47 | 48 | EVP_DigestInit( mdctx, md ); 49 | 50 | while (( rr = read( fd, buf, sizeof( buf ))) > 0 ) { 51 | size += rr; 52 | EVP_DigestUpdate( mdctx, buf, (unsigned int)rr ); 53 | } 54 | if ( rr < 0 ) { 55 | EVP_MD_CTX_free(mdctx); 56 | return( -1 ); 57 | } 58 | 59 | EVP_DigestFinal( mdctx, md_value, &md_len ); 60 | base64_e( md_value, md_len, cksum_b64 ); 61 | EVP_MD_CTX_free( mdctx ); 62 | 63 | return( size ); 64 | } 65 | 66 | off_t 67 | do_cksum( char *path, char *cksum_b64 ) 68 | { 69 | int fd; 70 | off_t size = 0; 71 | 72 | if (( fd = open( path, O_RDONLY, 0 )) < 0 ) { 73 | return( -1 ); 74 | } 75 | 76 | size = do_fcksum( fd, cksum_b64 ); 77 | 78 | if ( close( fd ) != 0 ) { 79 | return( -1 ); 80 | } 81 | 82 | return( size ); 83 | } 84 | 85 | #ifdef __APPLE__ 86 | 87 | /* 88 | * do_acksum calculates the checksum for the encoded apple single file of PATH 89 | * and returns it base64 encoded in cksum_b64 which must be of size 90 | * SZ_BASE64_E( EVP_MAX_MD_SIZE ). 91 | * 92 | * return values: 93 | * >= 0 number of bytes check summed 94 | * < 0 system error: errno set, no message given 95 | * 96 | * do_acksum should only be called on native HFS+ system. 97 | */ 98 | 99 | off_t 100 | do_acksum( char *path, char *cksum_b64, struct applefileinfo *afinfo ) 101 | { 102 | int dfd, rfd, rc; 103 | char buf[ 8192 ], rsrc_path[ MAXPATHLEN ]; 104 | off_t size = 0; 105 | extern struct as_header as_header; 106 | struct as_entry as_entries_endian[ 3 ]; 107 | unsigned int md_len; 108 | extern EVP_MD *md; 109 | EVP_MD_CTX *mdctx = EVP_MD_CTX_new(); 110 | unsigned char md_value[ SZ_BASE64_D( SZ_BASE64_E( EVP_MAX_MD_SIZE ) ) ]; 111 | 112 | EVP_DigestInit( mdctx, md ); 113 | 114 | /* checksum applesingle header */ 115 | EVP_DigestUpdate( mdctx, (char *)&as_header, AS_HEADERLEN ); 116 | size += (size_t)AS_HEADERLEN; 117 | 118 | /* endian handling, sum big-endian header entries */ 119 | memcpy( &as_entries_endian, &afinfo->as_ents, 120 | ( 3 * sizeof( struct as_entry ))); 121 | as_entry_netswap( &as_entries_endian[ AS_FIE ] ); 122 | as_entry_netswap( &as_entries_endian[ AS_RFE ] ); 123 | as_entry_netswap( &as_entries_endian[ AS_DFE ] ); 124 | 125 | /* checksum header entries */ 126 | EVP_DigestUpdate( mdctx, (char *)&as_entries_endian, 127 | (unsigned int)( 3 * sizeof( struct as_entry ))); 128 | size += sizeof( 3 * sizeof( struct as_entry )); 129 | 130 | /* checksum finder info data */ 131 | EVP_DigestUpdate( mdctx, afinfo->ai.ai_data, FINFOLEN ); 132 | size += FINFOLEN; 133 | 134 | /* checksum rsrc fork data */ 135 | if ( afinfo->as_ents[ AS_RFE ].ae_length > 0 ) { 136 | if ( snprintf( rsrc_path, MAXPATHLEN, "%s%s", 137 | path, _PATH_RSRCFORKSPEC ) >= MAXPATHLEN ) { 138 | errno = ENAMETOOLONG; 139 | EVP_MD_CTX_free(mdctx); 140 | return( -1 ); 141 | } 142 | 143 | if (( rfd = open( rsrc_path, O_RDONLY )) < 0 ) { 144 | EVP_MD_CTX_free(mdctx); 145 | return( -1 ); 146 | } 147 | while (( rc = read( rfd, buf, sizeof( buf ))) > 0 ) { 148 | EVP_DigestUpdate( mdctx, buf, (unsigned int)rc ); 149 | size += (size_t)rc; 150 | } 151 | if ( close( rfd ) < 0 ) { 152 | EVP_MD_CTX_free(mdctx); 153 | return( -1 ); 154 | } 155 | if ( rc < 0 ) { 156 | EVP_MD_CTX_free(mdctx); 157 | return( -1 ); 158 | } 159 | } 160 | 161 | if (( dfd = open( path, O_RDONLY, 0 )) < 0 ) { 162 | EVP_MD_CTX_free( mdctx ); 163 | return( -1 ); 164 | } 165 | /* checksum data fork */ 166 | while (( rc = read( dfd, buf, sizeof( buf ))) > 0 ) { 167 | EVP_DigestUpdate( mdctx, buf, (unsigned int)rc ); 168 | size += (size_t)rc; 169 | } 170 | if ( rc < 0 ) { 171 | EVP_MD_CTX_free( mdctx ); 172 | return( -1 ); 173 | } 174 | if ( close( dfd ) < 0 ) { 175 | EVP_MD_CTX_free( mdctx ); 176 | return( -1 ); 177 | } 178 | 179 | EVP_DigestFinal( mdctx, md_value, &md_len ); 180 | base64_e( ( unsigned char* ) md_value, md_len, cksum_b64 ); 181 | EVP_MD_CTX_free( mdctx ); 182 | 183 | return( size ); 184 | } 185 | #else /* __APPLE__ */ 186 | 187 | /* 188 | * stub fuction for non-hfs+ machines. 189 | * 190 | * return values: 191 | * -1 system error: non hfs+ system 192 | */ 193 | 194 | off_t 195 | do_acksum( char *path, char *cksum_b64, struct applefileinfo *afino ) 196 | { 197 | errno = EOPNOTSUPP; 198 | return( -1 ); 199 | } 200 | #endif /* __APPLE__ */ 201 | -------------------------------------------------------------------------------- /cksum.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | off_t do_fcksum( int fd, char *cksum_b64 ); 7 | off_t do_cksum( char *path, char *cksum_b64 ); 8 | off_t do_acksum( char *path, char *cksum_b64, struct applefileinfo *afinfo ); 9 | -------------------------------------------------------------------------------- /code.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "code.h" 15 | 16 | /* 17 | * Escape certain characters. This code must match decode() *and* 18 | * argcargv(). 19 | */ 20 | char * 21 | encode( char *line ) 22 | { 23 | /* static */ 24 | static char buf[ 2 * MAXPATHLEN ]; 25 | char *temp; 26 | 27 | if ( strlen( line ) > MAXPATHLEN ) { 28 | return( NULL ); 29 | } 30 | 31 | temp = buf; 32 | for ( ; *line != '\0'; line++, temp++ ) { 33 | switch ( *line ) { 34 | case ' ' : 35 | *temp = '\\'; 36 | temp++; 37 | *temp = 'b'; 38 | break; 39 | case '\t' : 40 | *temp = '\\'; 41 | temp++; 42 | *temp = 't'; 43 | break; 44 | case '\n': 45 | *temp = '\\'; 46 | temp++; 47 | *temp = 'n'; 48 | break; 49 | case '\r': 50 | *temp = '\\'; 51 | temp++; 52 | *temp = 'r'; 53 | break; 54 | case '\\': 55 | *temp = '\\'; 56 | temp++; 57 | *temp = '\\'; 58 | break; 59 | default : 60 | *temp = *line; 61 | break; 62 | } 63 | } 64 | 65 | *temp = '\0'; 66 | return( buf ); 67 | } 68 | 69 | char * 70 | decode( char *line ) 71 | { 72 | /* static */ 73 | static char buf[ MAXPATHLEN ]; 74 | char *temp, *end; 75 | 76 | if ( strlen( line ) > ( 2 * MAXPATHLEN )) { 77 | return( NULL ); 78 | } 79 | 80 | end = buf + MAXPATHLEN; 81 | temp = buf; 82 | 83 | for ( ; *line != '\0'; line++, temp++ ) { 84 | /* Check for buffer overflow - must have space for '\0' */ 85 | if ( temp >= end ) { 86 | return( NULL ); 87 | } 88 | switch( *line ) { 89 | case '\\': 90 | line++; 91 | switch( *line ) { 92 | case 'n': 93 | *temp = '\n'; 94 | break; 95 | case 't': 96 | *temp = '\t'; 97 | break; 98 | case 'b': 99 | *temp = ' '; 100 | break; 101 | case 'r': 102 | *temp = '\r'; 103 | break; 104 | case '\\': 105 | *temp = '\\'; 106 | break; 107 | default: 108 | break; 109 | } 110 | break; 111 | default: 112 | *temp = *line; 113 | break; 114 | } 115 | } 116 | 117 | *temp = '\0'; 118 | return( buf ); 119 | } 120 | -------------------------------------------------------------------------------- /code.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | char *encode( char * ); 7 | char *decode( char * ); 8 | -------------------------------------------------------------------------------- /command.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | int cmdloop( int, struct sockaddr_in * ); 7 | int command_k( char *, int ); 8 | char **special_t( char *, char * ); 9 | int keyword( int, char*[] ); 10 | extern char *path_radmind; 11 | 12 | struct command { 13 | char *c_name; 14 | int (*c_func)( SNET *, int, char *[] ); 15 | }; 16 | 17 | #define RADMIND_STAT_FMT "%s %s %o %d %d %" PRItimet "d %" PRIofft "d %s\r\n" 18 | -------------------------------------------------------------------------------- /config.h.in: -------------------------------------------------------------------------------- 1 | /* Size of off_T */ 2 | #undef SIZEOF_OFF_T 3 | 4 | /* Version number of package */ 5 | #undef VERSION 6 | 7 | /* Define to make fseeko etc. visible, on some hosts. */ 8 | #undef _LARGEFILE_SOURCE 9 | 10 | /* Define for large files, on AIX-style hosts. */ 11 | #undef _LARGE_FILES 12 | 13 | /* Number of bits in a file offset, on hosts where this is settable. 14 | case in 15 | # HP-UX 10.20 and later 16 | hpux10.2-90-9* | hpux11-9* | hpux2-90-9*) 17 | ac_cv_sys_file_offset_bits=64 ;; 18 | esac */ 19 | #undef _FILE_OFFSET_BITS 20 | 21 | #undef HAVE_LIBSSL 22 | #undef HAVE_X509_VERIFY_PARAM 23 | #undef HAVE_ZEROCONF 24 | 25 | #undef HAVE_LIBPAM 26 | #undef HAVE_PAM_PAM_APPL_H 27 | #undef HAVE_SECURITY_PAM_APPL_H 28 | 29 | #undef HAVE_DNSSD 30 | #undef HAVE_LCHOWN 31 | #undef HAVE_LCHMOD 32 | #undef HAVE_ZLIB 33 | 34 | #undef HAVE_WAIT4 35 | #undef HAVE_STRTOLL 36 | 37 | #undef MAJOR_IN_SYSMACROS 38 | #undef MAJOR_IN_MKDEV 39 | 40 | #ifndef MIN 41 | #define MIN(a,b) ((a)<(b)?(a):(b)) 42 | #endif /* MIN */ 43 | 44 | #ifndef MAX 45 | #define MAX(a,b) ((a)>(b)?(a):(b)) 46 | #endif /* MAX */ 47 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | 2 | # Process this file with autoconf to produce a configure script. 3 | AC_INIT(radmind, VERSION, radmind@umich.edu) 4 | AC_CONFIG_HEADER(config.h) 5 | AC_PREREQ(2.52) 6 | AC_COPYRIGHT([Copyright (c) 2003 Regents of The University of Michigan. All Rights Reserved.]) 7 | AC_CONFIG_SRCDIR([applefile.c]) 8 | 9 | # Set up variables 10 | AC_ARG_VAR(diffpath, [path to diff utility]) 11 | AC_ARG_VAR(echopath, [path to echo utility]) 12 | 13 | AC_ARG_WITH(server, AC_HELP_STRING([--with-server=SERVER], [default radmind server]), server="$withval", server="radmind" ) 14 | AC_SUBST(server) 15 | 16 | AC_ARG_WITH(authlevel, AC_HELP_STRING([--with-authlevel=AUTHLEVEL], [default TLS authorization level]), authlevel="$withval", authlevel="0" ) 17 | AC_SUBST(authlevel) 18 | 19 | AC_ARG_WITH(radminddir, AC_HELP_STRING([--with-radminddir=DIR], [default radmind server storage]), radminddir="$withval", radminddir="/var/radmind" ) 20 | AC_SUBST(radminddir) 21 | 22 | AC_ARG_WITH(maxconnections, AC_HELP_STRING([--with-max-connections=MAX], [maximum number of simultaneous connections]), maxconnections="$withval", maxconnections=0 ) 23 | AC_SUBST(maxconnections) 24 | 25 | AC_ARG_WITH(maildomain, AC_HELP_STRING([--with-maildomain=DOMAIN], [default radmind mail domain]), maildomain="$withval", maildomain="" ) 26 | AC_SUBST(maildomain) 27 | 28 | build_date=`date "+%B %d, %Y"` 29 | AC_SUBST(build_date) 30 | 31 | #AC_ARG_WITH(certdir, AC_HELP_STRING([--cert=DIR], [default certificate location]), certdir="$withval", certdir="/var/radmind/cert" ) 32 | #AC_SUBST(certdir) 33 | 34 | AC_CANONICAL_SYSTEM 35 | 36 | # Checks for programs. 37 | AC_PROG_AWK 38 | AC_PROG_CC 39 | AC_PROG_INSTALL 40 | AC_PATH_PROG(diffpath, diff) 41 | AC_PATH_PROG(echopath, echo) 42 | AC_PATH_PROG(mktemppath, mktemp) 43 | AC_SYS_LARGEFILE 44 | 45 | # Check sizes 46 | AC_CHECK_SIZEOF(off_t) 47 | AC_CHECK_SIZEOF(time_t) 48 | 49 | # check early to make any required changes to environment for following tests. 50 | CHECK_UNIVERSAL_BINARIES 51 | 52 | # mute Mac OS X's helpful notices that using dylib OpenSSL 53 | MACOSX_MUTE_DEPRECATION_WARNINGS 54 | 55 | # Checks for header files 56 | 57 | # glibc 2.25 still includes sys/sysmacros.h in sys/types.h but emits 58 | # deprecation warning which causes compilation failure later with -Werror. 59 | # So use -Werror here as well to force proper sys/sysmacros.h detection. 60 | SAVED_CFLAGS="$CFLAGS" 61 | CFLAGS="$HOST_CFLAGS -Werror" 62 | AC_HEADER_MAJOR 63 | CFLAGS="$SAVED_CFLAGS" 64 | 65 | 66 | # Checks for libraries. 67 | AC_CHECK_LIB(c, inet_aton, libc_inet_aton=yes) 68 | if test x$libc_inet_aton != xyes; then 69 | AC_CHECK_LIB(resolv, inet_aton) 70 | fi 71 | if test x$host_vendor = xapply; then 72 | AC_CHECK_LIB(c, lchown, [AC_DEFINE(HAVE_LCHOWN)], []) 73 | AC_CHECK_LIB(c, lchmod, [AC_DEFINE(HAVE_LCHMOD)], []) 74 | fi 75 | AC_CHECK_LIB(nsl, gethostbyaddr) 76 | AC_CHECK_LIB([socket], [socket]) 77 | AC_CHECK_LIB([ssl], [SSL_accept], , [CHECK_SSL]) 78 | AC_CHECK_HEADER([openssl/ssl.h], [], [AC_MSG_ERROR([header file 79 | is required for this software. You may be running RedHat 9. If so, see the FAQ or the README for further instructions.])]) 80 | AC_CHECK_LIB([crypto], [SSLeay_version], , [CHECK_SSL]) 81 | AC_CHECK_LIB([crypto], [X509_VERIFY_PARAM_set_flags], [AC_DEFINE(HAVE_X509_VERIFY_PARAM)], []) 82 | 83 | # PAM 84 | AC_ARG_WITH([pam], AC_HELP_STRING([--with-pam=PATH], [Pluggable Authentication Module support (default: /usr)]), [], with_pam=/usr) 85 | if test x_"$with_pam" != x_no; then 86 | CPPFLAGS="${CPPFLAGS} -I$with_pam/include" 87 | LDFLAGS="${LDFLAGS} -L$with_pam/lib" 88 | AC_CHECK_LIB([pam], [pam_start], 89 | [ 90 | AC_CHECK_HEADERS(pam/pam_appl.h, , [AC_CHECK_HEADERS(security/pam_appl.h)]) 91 | AC_DEFINE(HAVE_LIBPAM) 92 | LIBS="$LIBS -lpam"; 93 | ] 94 | ) 95 | fi 96 | AC_CHECK_HEADER([dns_sd.h], [AC_DEFINE(HAVE_DNSSD)], [], []) 97 | AC_CHECK_LIB(dns_sd, DNSServiceRegister) 98 | 99 | CHECK_ZLIB 100 | 101 | # HPUX lacks wait4 and strtoll 102 | AC_CHECK_FUNCS(wait4 strtoll) 103 | 104 | # Miscellaneous: 105 | if test x_"$OPTOPTS" = x_; then 106 | if test x_$GCC = x_yes; then 107 | OPTOPTS="$OPTOPTS -Wall -Wmissing-prototypes" 108 | fi 109 | if test x_$build_vendor = x_hp; then 110 | OPTOPTS="$OPTOPTS -D_XOPEN_SOURCE -D_XOPEN_SOURCE_EXTENDED=1" 111 | fi 112 | fi 113 | AC_SUBST(OPTOPTS) 114 | 115 | SET_NO_SASL 116 | AC_CONFIG_SUBDIRS(libsnet) 117 | AC_CONFIG_FILES(Makefile) 118 | AC_OUTPUT 119 | -------------------------------------------------------------------------------- /connect.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | #ifdef HAVE_ZLIB 26 | #include 27 | #endif /* HAVE_ZLIB */ 28 | 29 | #include 30 | 31 | #include "applefile.h" 32 | #include "cksum.h" 33 | #include "connect.h" 34 | #include "argcargv.h" 35 | 36 | #define RADMIND_IANA_PORT 6222 37 | #define RADMIND_LEGACY_PORT 6662 38 | 39 | extern void (*logger)( char * ); 40 | extern int verbose; 41 | struct timeval timeout = { 60, 0 }; 42 | extern int errno; 43 | extern SSL_CTX *ctx; 44 | 45 | 46 | #ifdef HAVE_ZLIB 47 | int zlib_level = 0; 48 | #endif 49 | 50 | void 51 | v_logger( char *line ) 52 | { 53 | printf( "<<< %s\n", line ); 54 | return; 55 | } 56 | 57 | static SNET * 58 | connectsn2( struct sockaddr_in *sin ) 59 | { 60 | int s; 61 | int one = 1; 62 | int connectsn2_errno = 0; 63 | SNET *sn = NULL; 64 | struct protoent *proto; 65 | 66 | if (( s = socket( PF_INET, SOCK_STREAM, 0 )) < 0 ) { 67 | perror( "socket" ); 68 | exit( 2 ); 69 | } 70 | 71 | if (( proto = getprotobyname( "tcp" )) == NULL ) { 72 | perror( "getprotobyname" ); 73 | exit( 2 ); 74 | } 75 | if ( setsockopt( s, proto->p_proto, TCP_NODELAY, &one, 76 | sizeof( one )) != 0 ) { 77 | perror( "snet_setopt" ); 78 | exit( 2 ); 79 | } 80 | 81 | if ( verbose ) printf( "trying %s:%u... ", inet_ntoa( sin->sin_addr ), 82 | ntohs( sin->sin_port )); 83 | if ( connect( s, (struct sockaddr *)sin, 84 | sizeof( struct sockaddr_in )) != 0 ) { 85 | connectsn2_errno = errno; 86 | if ( verbose ) printf( "failed: %s\n", strerror( errno )); 87 | (void)close( s ); 88 | errno = connectsn2_errno; 89 | return( NULL ); 90 | } 91 | if ( verbose ) printf( "success!\n" ); 92 | if (( sn = snet_attach( s, 1024 * 1024 )) == NULL ) { 93 | perror( "snet_attach" ); 94 | exit( 2 ); 95 | } 96 | 97 | return( sn ); 98 | } 99 | 100 | SNET * 101 | connectsn( char *host, unsigned short port ) 102 | { 103 | int i; 104 | struct hostent *he; 105 | struct sockaddr_in sin; 106 | struct servent *se = NULL; 107 | SNET *sn = NULL; 108 | 109 | memset( &sin, 0, sizeof( struct sockaddr_in )); 110 | sin.sin_family = AF_INET; 111 | 112 | #ifdef notdef 113 | /* 114 | * this code should be enabled only to deal with bugs in 115 | * the gethostbyname() routine 116 | */ 117 | if (( sin.sin_addr.s_addr = inet_addr( host )) != -1 ) { 118 | return( connectsn2( &sin )); 119 | } 120 | #endif // notdef 121 | 122 | if (( he = gethostbyname( host )) == NULL ) { 123 | fprintf( stderr, "%s: Unknown host\n", host ); 124 | return( NULL ); 125 | } 126 | 127 | if ( port == 0 ) { 128 | /* maybe radmind's in /etc/services. if not, use default. */ 129 | se = getservbyname( "radmind", "tcp" ); 130 | } 131 | 132 | for ( i = 0; he->h_addr_list[ i ] != NULL; i++ ) { 133 | memcpy( &sin.sin_addr.s_addr, he->h_addr_list[ i ], 134 | (unsigned int)he->h_length ); 135 | if ( se != NULL ) { 136 | /* getservbyname returns port numbers in network byte order */ 137 | sin.sin_port = se->s_port; 138 | } else if (( sin.sin_port = port ) == 0 ) { 139 | sin.sin_port = htons( RADMIND_IANA_PORT ); 140 | } 141 | 142 | /* 143 | * radmind's original port was 6662, but got 144 | * registered as 6222 with IANA, and will show 145 | * up in future /etc/services as 6222. during 146 | * the transition, fall back to trying the 147 | * legacy port if the new port connection fails. 148 | */ 149 | if (( sn = connectsn2( &sin )) == NULL && port == 0 ) { 150 | /* try connecting to old non-IANA registered port */ 151 | sin.sin_port = htons( RADMIND_LEGACY_PORT ); 152 | sn = connectsn2( &sin ); 153 | } 154 | if ( sn != NULL ) { 155 | return( sn ); 156 | } 157 | } 158 | fprintf( stderr, "connection to %s failed: %s\n", 159 | inet_ntoa( sin.sin_addr ), strerror( errno )); 160 | fprintf( stderr, "%s: connection failed\n", host ); 161 | return( NULL ); 162 | } 163 | 164 | int 165 | closesn( SNET *sn ) 166 | { 167 | char *line; 168 | struct timeval tv; 169 | 170 | /* Close network connection */ 171 | if ( snet_writef( sn, "QUIT\r\n" ) < 0 ) { 172 | fprintf( stderr, "QUIT failed: %s\n", strerror( errno )); 173 | exit( 2 ); 174 | } 175 | tv = timeout; 176 | if (( line = snet_getline_multi( sn, logger, &tv )) == NULL ) { 177 | fprintf( stderr, "close failed: %s\n", strerror( errno )); 178 | exit( 2 ); 179 | } 180 | if ( *line != '2' ) { 181 | perror( line ); 182 | return( -1 ); 183 | } 184 | if ( snet_close( sn ) != 0 ) { 185 | fprintf( stderr, "snet_close failed: %s\n", strerror( errno )); 186 | exit( 2 ); 187 | } 188 | return( 0 ); 189 | } 190 | 191 | char ** 192 | get_capabilities( SNET *sn ) 193 | { 194 | char *line; 195 | char temp[ MAXPATHLEN ]; 196 | char **capa = NULL; 197 | int i, ac; 198 | char **av; 199 | struct timeval tv; 200 | 201 | while( 1 ) { 202 | tv = timeout; 203 | if (( line = snet_getline( sn, &tv )) == NULL ) { 204 | fprintf( stderr, "connection failed\n" ); 205 | return( NULL ); 206 | } 207 | if ( *line != '2' ) { 208 | fprintf( stderr, "%s\n", line ); 209 | return( NULL ); 210 | } 211 | if ( verbose ) printf( "<<< %s\n", line ); 212 | strcpy( temp, line+4 ); 213 | if (( ac = argcargv( temp, &av )) != 0 ) { 214 | if ( strncasecmp( "CAPAbilities", av[0], MIN( 12, strlen( av[0] ))) == 0 ) { 215 | capa = malloc( sizeof(char *)*ac ); 216 | for ( i = 0; i+1 < ac; i++ ) { 217 | capa[i] = strdup( av[i+1] ); 218 | } 219 | capa[i] = NULL; 220 | } 221 | } 222 | switch( line[3] ) { 223 | case ' ': 224 | if( !capa ) { 225 | capa = malloc( sizeof( char * )); 226 | *capa = NULL; 227 | } 228 | return ( capa ); 229 | case '-': 230 | break; 231 | default: 232 | fprintf ( stderr, "%s\n", line ); 233 | return ( NULL ); 234 | } 235 | } 236 | } 237 | 238 | #ifdef HAVE_ZLIB 239 | int 240 | negotiate_compression( SNET *sn, char **capa ) 241 | { 242 | char *name = NULL; 243 | char *line; 244 | int type = 0; 245 | int level = 0; 246 | struct timeval tv; 247 | 248 | /* Place compression algorithms in descending order of desirability */ 249 | if ( zlib_level ) { 250 | /* walk through capabilities looking for "ZLIB" */ 251 | if ( check_capability( "ZLIB", capa ) == 1 ) { 252 | name = "ZLIB"; 253 | type = SNET_ZLIB; 254 | level = zlib_level; 255 | } 256 | 257 | if ( level == 0 ) { 258 | fprintf( stderr, "compression capability mismatch, " 259 | "compression disabled\n" ); 260 | return( 0 ); 261 | } 262 | } 263 | 264 | if ( verbose ) printf( ">>> COMP %s %d\n", name, level ); 265 | snet_writef( sn, "COMP %s %d\r\n", name, level ); 266 | 267 | tv = timeout; 268 | if (( line = snet_getline( sn, &tv )) == NULL ) { 269 | perror( "snet_getline" ); 270 | return( -1 ); 271 | } 272 | if( verbose ) printf( "<<< %s\n", line ); 273 | if ( *line != '3' ) { 274 | fprintf( stderr, "%s\n", line ); 275 | return( -1 ); 276 | } 277 | 278 | if ( snet_setcompression( sn, type, level ) < 0 ) { 279 | perror( "snet_setcompression" ); 280 | return( -1 ); 281 | } 282 | 283 | tv = timeout; 284 | if (( line = snet_getline( sn, &tv )) == NULL ) { 285 | perror( "snet_getline" ); 286 | return( -1 ); 287 | } 288 | if( verbose ) printf( "<<< %s\n", line ); 289 | if ( *line != '2' ) { 290 | fprintf( stderr, "%s\n", line ); 291 | return( -1 ); 292 | } 293 | 294 | return( 0 ); 295 | } 296 | 297 | int 298 | print_stats( SNET *sn ) 299 | { 300 | z_stream in_stream, out_stream; 301 | 302 | if ( snet_flags( sn ) & SNET_ZLIB ) { 303 | in_stream = snet_zistream( sn ); 304 | out_stream = snet_zostream( sn ); 305 | 306 | #define RATIO(a,b) (((double)(a))/((double)(b))) 307 | if ( verbose ) { 308 | printf( "zlib stats +++ In: %lu:%lu (%.3f:1) " 309 | "+++ Out: %lu:%lu (%.3f:1)\n", 310 | in_stream.total_out, in_stream.total_in, 311 | RATIO( in_stream.total_out, in_stream.total_in ), 312 | out_stream.total_in, out_stream.total_out, 313 | RATIO( out_stream.total_in, out_stream.total_out )); 314 | } else { 315 | syslog( LOG_INFO, "zlib stats +++ In: %lu:%lu (%.3f:1) " 316 | "+++ Out: %lu:%lu (%.3f:1)\n", 317 | in_stream.total_out, in_stream.total_in, 318 | RATIO( in_stream.total_out, in_stream.total_in ), 319 | out_stream.total_in, out_stream.total_out, 320 | RATIO( out_stream.total_in, out_stream.total_out )); 321 | } 322 | } 323 | return( 0 ); 324 | } 325 | #endif /* HAVE_ZLIB */ 326 | 327 | /* 328 | * check_capabilities: check to see if type is a listed capability 329 | * 330 | * return codes: 331 | * 0: type not in capability list 332 | * 1: type in capability list 333 | */ 334 | int 335 | check_capability( char *type, char **capa ) 336 | { 337 | char **p; 338 | 339 | /* walk through capabilities looking for "REPO" */ 340 | for ( p = capa; *p; p++ ) { 341 | if ( !strncasecmp( type, *p, MIN( 4, strlen( *p )))) { 342 | return( 1 ); 343 | } 344 | } 345 | return( 0 ); 346 | } 347 | -------------------------------------------------------------------------------- /connect.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | SNET * connectsn( char *host, unsigned short port ); 7 | int closesn( SNET *sn ); 8 | char **get_capabilities( SNET * ); 9 | #ifdef HAVE_ZLIB 10 | int negotiate_compression( SNET *, char ** ); 11 | int print_stats( SNET * ); 12 | extern int zlib_level; 13 | #endif /* HAVE_ZLIB */ 14 | 15 | int retr( SNET *sn, char *pathdesc, char *path, char *temppath, 16 | mode_t tempmode, off_t transize, char *trancksum ); 17 | int retr_applefile( SNET *sn, char *pathdesc, char *path, char *temppath, 18 | mode_t tempmode, off_t transize, char *trancksum ); 19 | 20 | int n_stor_file( SNET *sn, char *pathdesc, char *path ); 21 | int stor_file( SNET *sn, char *pathdesc, char *path, off_t transize, 22 | char *trancksum ); 23 | int n_stor_applefile( SNET *sn, char *pathdesc, char *path ); 24 | int stor_applefile( SNET *sn, char *pathdesc, char *path, off_t transize, 25 | char *trancksum, struct applefileinfo *afinfo ); 26 | int stor_response( SNET *sn, int *respcount, struct timeval * ); 27 | void v_logger( char *string); 28 | int check_capability( char *type, char **capa ); 29 | -------------------------------------------------------------------------------- /contrib/fsspy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2008 The Regents of The University of Michigan 3 | * All Rights Reserved. 4 | * 5 | * Permission to use, copy, modify, and distribute this software and 6 | * its documentation for any purpose and without fee is hereby granted, 7 | * provided that the above copyright notice appears in all copies and 8 | * that both that copyright notice and this permission notice appear 9 | * in supporting documentation, and that the name of The University 10 | * of Michigan not be the software without specific, written prior 11 | * permission. This software is supplied as is without expressed or 12 | * implied warranties of any kind. 13 | * 14 | * Written by Andrew Mortensen, Dec. 2008. 15 | */ 16 | 17 | /* 18 | * To compile: 19 | gcc -g -framework CoreFoundation -framework CoreServices \ 20 | -o fsspy fsspy.c 21 | * 22 | */ 23 | 24 | #include 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | extern int errno; 36 | 37 | struct event { 38 | char *e_path; 39 | unsigned long long e_id; 40 | unsigned long e_flags; 41 | struct event *e_next; 42 | }; 43 | 44 | struct event *event_head = NULL; 45 | 46 | int debug = 0; 47 | int case_sensitive = 1; 48 | int delayed_print = 0; 49 | int all_paths = 0; 50 | char *prefix = NULL; 51 | 52 | int 53 | ischild( char *child, char *parent ) 54 | { 55 | int rc, len; 56 | 57 | if ( parent == NULL ) { 58 | return( 1 ); 59 | } 60 | 61 | if (( len = strlen( parent )) > strlen( child )) { 62 | return( 0 ); 63 | } 64 | if ( len == 1 && *parent == '/' ) { 65 | return(( *child == '/' )); 66 | } 67 | 68 | if ( case_sensitive ) { 69 | rc = strncmp( parent, child, len ); 70 | } else { 71 | rc = strncasecmp( parent, child, len ); 72 | } 73 | if ( rc == 0 && ( child[ len ] == '/' || child[ len ] == '\0' )) { 74 | return( 1 ); 75 | } 76 | 77 | return( 0 ); 78 | } 79 | 80 | struct event * 81 | event_new( char *path, unsigned long long id, unsigned long flags ) 82 | { 83 | struct event *new; 84 | int len; 85 | 86 | if (( new = (struct event *)malloc( sizeof( struct event ))) == NULL ) { 87 | return( NULL ); 88 | } 89 | 90 | /* user may have specified a prefix for the path. */ 91 | len = strlen( path ) + 1; 92 | if ( prefix != NULL ) { 93 | len += strlen( prefix ); 94 | } 95 | if (( new->e_path = (char *)malloc( len )) == NULL ) { 96 | free( new ); 97 | return( NULL ); 98 | } 99 | if ( prefix != NULL ) { 100 | strcpy( new->e_path, prefix ); 101 | strcat( new->e_path, path ); 102 | } else { 103 | strcpy( new->e_path, path ); 104 | } 105 | 106 | /* the fsevents API returns paths with a trailing slash. chop it. */ 107 | len = strlen( new->e_path ); 108 | if ( new->e_path[ len - 1 ] == '/' ) { 109 | new->e_path[ len - 1 ] = '\0'; 110 | } 111 | 112 | new->e_id = id; 113 | new->e_flags = flags; 114 | new->e_next = NULL; 115 | 116 | return( new ); 117 | } 118 | 119 | void 120 | event_insert( struct event **head, struct event *new ) 121 | { 122 | struct event **cur; 123 | struct event *tmp; 124 | int rc; 125 | 126 | /* must use while loop here since we're traversing and (maybe) deleting. */ 127 | cur = head; 128 | 129 | while ( *cur != NULL ) { 130 | if ( !all_paths && ischild( new->e_path, (*cur)->e_path )) { 131 | /* drop new node. we've already got the parent in the list. */ 132 | free( new->e_path ); 133 | free( new ); 134 | return; 135 | } else if ( !all_paths && ischild((*cur)->e_path, new->e_path )) { 136 | /* the new node is the cur parent. drop cur. */ 137 | tmp = *cur; 138 | *cur = (*cur)->e_next; 139 | free( tmp->e_path ); 140 | free( tmp ); 141 | /* the deletion takes care of the increment. */ 142 | } else { 143 | if ( case_sensitive ) { 144 | rc = strcmp( new->e_path, (*cur)->e_path ); 145 | } else { 146 | rc = strcasecmp( new->e_path, (*cur)->e_path ); 147 | } 148 | 149 | if ( rc == 0 ) { 150 | /* new is already in the list. drop it. */ 151 | free( new->e_path ); 152 | free( new ); 153 | return; 154 | } else if ( rc < 0 ) { 155 | break; 156 | } else { 157 | cur = &(*cur)->e_next; 158 | } 159 | } 160 | } 161 | 162 | new->e_next = *cur; 163 | *cur = new; 164 | } 165 | 166 | void 167 | event_print( struct event **head ) 168 | { 169 | struct event *cur, *tmp; 170 | 171 | for ( cur = *head; cur != NULL; cur = tmp ) { 172 | printf( "%s\n", cur->e_path ); 173 | 174 | tmp = cur->e_next; 175 | 176 | free( cur->e_path ); 177 | free( cur ); 178 | } 179 | 180 | *head = NULL; 181 | } 182 | 183 | void 184 | fsevent_callback( ConstFSEventStreamRef ref, void *info, 185 | size_t nevents, void *eventpaths, 186 | const FSEventStreamEventFlags eflags[], 187 | const FSEventStreamEventId eids[] ) 188 | { 189 | struct event *new; 190 | char **paths = eventpaths; 191 | int i; 192 | time_t now; 193 | 194 | #define FSEVENTID "ID" 195 | #define FSEVENTFLAGS "Flags" 196 | #define FSEVENTPATH "Path" 197 | 198 | if ( debug && nevents > 0 ) { 199 | printf( "# %-8s %-10s %s\n", FSEVENTID, FSEVENTFLAGS, FSEVENTPATH ); 200 | } 201 | 202 | for ( i = 0; i < nevents; i++ ) { 203 | if (( new = event_new( paths[ i ], eids[ i ], 204 | eflags[ i ] )) == NULL ) { 205 | perror( "event_new: malloc" ); 206 | exit( 2 ); 207 | } 208 | event_insert( &event_head, new ); 209 | 210 | if ( debug ) { 211 | printf( "%-10llu %-10lu %s\n", eids[ i ], ( unsigned long )eflags[ i ], paths[ i ] ); 212 | } 213 | } 214 | 215 | if ( nevents > 0 && !delayed_print ) { 216 | event_print( &event_head ); 217 | } 218 | } 219 | 220 | /* called when the user-specified run time ends */ 221 | void 222 | timer_callback( CFRunLoopRef runloop, void *info ) 223 | { 224 | FSEventStreamRef fsstream = (FSEventStreamRef)info; 225 | 226 | /* block until all events are cleared. */ 227 | FSEventStreamFlushSync( fsstream ); 228 | 229 | CFRunLoopStop( CFRunLoopGetCurrent()); 230 | } 231 | 232 | int 233 | main( int ac, char *av[] ) 234 | { 235 | CFStringRef *paths = NULL; 236 | CFArrayRef watchpaths = NULL; 237 | FSEventStreamRef fsstream = NULL; 238 | CFAbsoluteTime latency = 2.0; 239 | CFRunLoopTimerRef timer; 240 | SInt32 runloop_rc; 241 | int watchtime = 0; 242 | int c; 243 | int i; 244 | int err = 0; 245 | 246 | extern int optind; 247 | extern char *optarg; 248 | 249 | while (( c = getopt( ac, av, "adIl:p:t:w" )) != -1 ) { 250 | switch ( c ) { 251 | case 'a': /* print all paths regardless of overlap. */ 252 | all_paths = 1; 253 | break; 254 | 255 | case 'd': /* debug */ 256 | debug = 1; 257 | break; 258 | 259 | case 'I': /* case-insensitive path comparisons */ 260 | case_sensitive = 0; 261 | break; 262 | 263 | case 'l': /* latency */ 264 | errno = 0; 265 | latency = strtod( optarg, NULL ); 266 | if ( errno ) { 267 | fprintf( stderr, "strtod %s: %s\n", optarg, strerror( errno )); 268 | exit( 1 ); 269 | } 270 | if ( latency < 0.0 ) { 271 | fprintf( stderr, "latency cannot be negative\n" ); 272 | exit( 1 ); 273 | } 274 | break; 275 | 276 | case 'p': /* prefix for path output. */ 277 | if (( prefix = strdup( optarg )) == NULL ) { 278 | perror( "strdup" ); 279 | exit( 2 ); 280 | } 281 | break; 282 | 283 | case 't': /* time in seconds to watch given paths */ 284 | errno = 0; 285 | watchtime = strtoul( optarg, NULL, 10 ); 286 | if ( errno ) { 287 | fprintf( stderr, "strtoul %s: %s\n", optarg, strerror( errno )); 288 | exit( 1 ); 289 | } 290 | break; 291 | 292 | case 'w': /* print paths after watchtime elapses. */ 293 | delayed_print = 1; 294 | break; 295 | 296 | default: 297 | err++; 298 | break; 299 | } 300 | } 301 | 302 | if ( delayed_print && !watchtime ) { 303 | err++; 304 | } 305 | 306 | if ( err || ( ac - optind ) < 1 ) { 307 | fprintf( stderr, "usage: %s [ -adI ] [ -l delay_in_seconds ] " 308 | "[ -p path_prefix ] [ -t run_time_in_seconds [ -w ]] " 309 | "path1 [path2 path3 ... pathN]\n", av[ 0 ] ); 310 | exit( 1 ); 311 | } 312 | 313 | if (( paths = ( CFStringRef * )malloc(( ac - 1 ) * sizeof( CFStringRef ))) 314 | == NULL ) { 315 | perror( "malloc" ); 316 | exit( 2 ); 317 | } 318 | for ( i = 1; i < ac; i++ ) { 319 | paths[ i - 1 ] = CFStringCreateWithCString( kCFAllocatorDefault, 320 | av[ i ], kCFStringEncodingUTF8 ); 321 | if ( paths[ i - 1 ] == NULL ) { 322 | fprintf( stderr, "%s: failed to create CFStringRef\n", av[ i ] ); 323 | exit( 2 ); 324 | } 325 | } 326 | watchpaths = CFArrayCreate( kCFAllocatorDefault, 327 | ( const void ** )paths, 328 | ac - 1, 329 | &kCFTypeArrayCallBacks ); 330 | if ( watchpaths == NULL ) { 331 | fprintf( stderr, "CFArrayCreate failed\n" ); 332 | exit( 2 ); 333 | } 334 | 335 | for ( i = 0; i < ( ac - 1 ); i++ ) { 336 | CFRelease( paths[ i ] ); 337 | } 338 | free( paths ); 339 | 340 | fsstream = FSEventStreamCreate( kCFAllocatorDefault, &fsevent_callback, 341 | NULL, watchpaths, 342 | kFSEventStreamEventIdSinceNow, 343 | latency, kFSEventStreamCreateFlagNone ); 344 | if ( fsstream == NULL ) { 345 | fprintf( stderr, "FSEventStreamCreate failed\n" ); 346 | exit( 2 ); 347 | } 348 | 349 | /* line buffering to make sure we get the output */ 350 | setlinebuf( stdout ); 351 | 352 | FSEventStreamScheduleWithRunLoop( fsstream, 353 | CFRunLoopGetCurrent(), kCFRunLoopDefaultMode ); 354 | if ( !FSEventStreamStart( fsstream )) { 355 | fprintf( stderr, "FSEventStreamStart failed\n" ); 356 | exit( 2 ); 357 | } 358 | 359 | if ( watchtime ) { 360 | CFRunLoopTimerContext context = { 0, fsstream, NULL, NULL, NULL }; 361 | timer = CFRunLoopTimerCreate( kCFAllocatorDefault, 362 | watchtime + CFAbsoluteTimeGetCurrent(), 363 | 0, 0, 0, 364 | (CFRunLoopTimerCallBack)timer_callback, 365 | &context ); 366 | if ( timer == NULL ) { 367 | fprintf( stderr, "CFRunLoopTimerCreate failed\n" ); 368 | exit( 2 ); 369 | } 370 | CFRunLoopAddTimer( CFRunLoopGetCurrent(), 371 | timer, kCFRunLoopDefaultMode ); 372 | } 373 | 374 | CFRunLoopRun(); 375 | 376 | if ( delayed_print ) { 377 | event_print( &event_head ); 378 | } 379 | 380 | FSEventStreamStop( fsstream ); 381 | FSEventStreamInvalidate( fsstream ); 382 | FSEventStreamRelease( fsstream ); 383 | 384 | if ( prefix != NULL ) { 385 | free( prefix ); 386 | } 387 | 388 | return( 0 ); 389 | } 390 | -------------------------------------------------------------------------------- /contrib/specialist: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # specialist: assist creation of special files. 4 | 5 | PATH=/bin:/usr/bin:/usr/local/bin; export PATH 6 | 7 | SCRIPT=`basename "$0"` 8 | INPUT_FORMAT=${INPUT_FORMAT:=path} 9 | 10 | usage() { 11 | echo "usage: ${SCRIPT} [ -T ]" 1>&2 12 | exit 1 13 | } 14 | 15 | die() { 16 | msg=$* 17 | 18 | echo "${msg}" 1>&2 19 | exit 2 20 | } 21 | 22 | # create a special transcript line for the given path. 23 | specialize() { 24 | local path="$1" 25 | 26 | [ -n "${path}" -a -f "${path}" ] || die "Invalid path: ${path}" 27 | 28 | fsdiff -1 -c sha1 "${path}" 29 | return $? 30 | } 31 | 32 | specialize_transcript() { 33 | local path="" 34 | status=0 35 | 36 | while read type path remainder; do 37 | if [ x"${type}" != x"f" ]; then 38 | continue 39 | fi 40 | 41 | specialize "${path}" 42 | done 43 | } 44 | 45 | specialize_paths() { 46 | local path="" 47 | status=0 48 | 49 | while read path; do 50 | specialize "${path}" 51 | if [ $? -ne 0 ]; then 52 | status=1 53 | fi 54 | done 55 | 56 | return "${status}" 57 | } 58 | 59 | while getopts T opt; do 60 | case $opt in 61 | T) 62 | INPUT_FORMAT="transcript" 63 | ;; 64 | 65 | *) 66 | usage 67 | ;; 68 | 69 | esac 70 | done 71 | shift $((OPTIND - 1)) 72 | 73 | if [ x"${INPUT_FORMAT}" = x"transcript" ]; then 74 | specialize_transcript 75 | else 76 | specialize_paths 77 | fi 78 | 79 | exit $? 80 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | app: 4 | image: "ghcr.io/magnusviri/radmind:master" 5 | build: 6 | context: ./ 7 | ports: 8 | - "6222:6222" 9 | volumes: 10 | - ./radmind:/var/radmind 11 | -------------------------------------------------------------------------------- /docker/entrypoint: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eu 3 | 4 | if [ ! -e "/var/radmind/cert" ]; then 5 | mkdir -p /var/radmind/cert 6 | fi 7 | if [ ! -e "/var/radmind/client" ]; then 8 | mkdir /var/radmind/client 9 | fi 10 | if [ ! -e "/var/radmind/postapply" ]; then 11 | mkdir /var/radmind/postapply 12 | fi 13 | if [ ! -e "/var/radmind/preapply" ]; then 14 | mkdir /var/radmind/preapply 15 | fi 16 | if [ ! -e "/var/radmind/config" ]; then 17 | echo "* test.K" >> /var/radmind/config 18 | if [ ! -e "/var/radmind/command" ]; then 19 | mkdir /var/radmind/command 20 | fi 21 | if [ ! -e "/var/radmind/command/test.K" ]; then 22 | echo "# hi from radmind" > /var/radmind/command/test.K 23 | fi 24 | fi 25 | 26 | # Run radmind in the background because it doesn't log to stdout. 27 | 28 | /usr/local/sbin/radmind 29 | 30 | # Run rsyslog in foreground 31 | 32 | pidfile="/var/run/rsyslogd.pid" 33 | rm -f "${pidfile}" 34 | exec rsyslogd -n -f /etc/rsyslogd.conf -i "${pidfile}" 35 | -------------------------------------------------------------------------------- /docker/etc/rsyslog.d/imux.conf: -------------------------------------------------------------------------------- 1 | # http://www.rsyslog.com/doc/ 2 | 3 | # Input modules 4 | module(load="imuxsock") 5 | input(type="imuxsock" Socket="/var/run/rsyslog/dev/log" CreatePath="on") 6 | -------------------------------------------------------------------------------- /docker/etc/rsyslog.d/stdout.conf: -------------------------------------------------------------------------------- 1 | # http://www.rsyslog.com/doc/ 2 | 3 | # Output modes 4 | $ModLoad omstdout.so # provide messages to stdout 5 | 6 | # Actions 7 | *.* :omstdout: # send everything to stdout 8 | -------------------------------------------------------------------------------- /docker/etc/rsyslogd.conf: -------------------------------------------------------------------------------- 1 | # 2 | # http://www.rsyslog.com/doc/ 3 | # 4 | 5 | # Include all config files in /etc/rsyslog.d/ 6 | # 7 | $IncludeConfig /etc/rsyslog.d/*.conf 8 | -------------------------------------------------------------------------------- /hardlink.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "applefile.h" 15 | #include "transcript.h" 16 | 17 | struct devlist { 18 | struct devlist *d_next; 19 | dev_t d_dev; 20 | struct inolist *d_ilist; 21 | }; 22 | 23 | struct inolist { 24 | struct inolist *i_next; 25 | ino_t i_ino; 26 | char *i_name; 27 | int i_flag; 28 | }; 29 | 30 | 31 | static struct devlist *dev_head = NULL; 32 | 33 | static char *i_insert( struct devlist *dev_head, 34 | struct pathinfo *pinfo ); 35 | static struct devlist *d_insert( struct devlist **dev_head, 36 | struct pathinfo *pinfo ); 37 | void hardlink_free( void ); 38 | 39 | char * 40 | hardlink( struct pathinfo *pinfo ) 41 | { 42 | struct devlist *device; 43 | 44 | device = d_insert( &dev_head, pinfo ); 45 | 46 | return( i_insert( device, pinfo )); 47 | } 48 | 49 | static struct devlist * 50 | d_insert( struct devlist **dev_head, struct pathinfo *pinfo ) 51 | { 52 | struct devlist *new, **cur; 53 | 54 | for ( cur = dev_head; *cur != NULL; cur = &(*cur)->d_next ) { 55 | if ( pinfo->pi_stat.st_dev <= (*cur)->d_dev ) { 56 | break; 57 | } 58 | } 59 | 60 | if (( (*cur) != NULL ) && ( pinfo->pi_stat.st_dev == (*cur)->d_dev )) { 61 | return( *cur ); 62 | } 63 | 64 | if (( new = ( struct devlist * ) malloc( sizeof( struct devlist ))) 65 | == NULL ) { 66 | perror( "d_insert malloc" ); 67 | exit( 2 ); 68 | } 69 | 70 | new->d_dev = pinfo->pi_stat.st_dev; 71 | new->d_ilist = NULL; 72 | new->d_next = *cur; 73 | *cur = new; 74 | 75 | return( *cur ); 76 | } 77 | 78 | static char * 79 | i_insert( struct devlist *dev_head, struct pathinfo *pinfo ) 80 | { 81 | struct inolist *new, **cur; 82 | 83 | for ( cur = &dev_head->d_ilist; *cur != NULL; cur = &(*cur)->i_next ) { 84 | if ( pinfo->pi_stat.st_ino <= (*cur)->i_ino ) { 85 | break; 86 | } 87 | } 88 | 89 | if (( (*cur) != NULL ) && ( pinfo->pi_stat.st_ino == (*cur)->i_ino )) { 90 | return( (*cur)->i_name ); 91 | } 92 | 93 | if (( new = ( struct inolist * ) malloc( sizeof( struct inolist ))) 94 | == NULL ) { 95 | perror( "i_insert malloc" ); 96 | exit( 2 ); 97 | } 98 | 99 | if (( new->i_name = ( char * ) malloc( strlen( pinfo->pi_name ) + 1 )) 100 | == NULL ) { 101 | perror( "i_insert malloc" ); 102 | exit( 2 ); 103 | } 104 | 105 | strcpy( new->i_name, pinfo->pi_name ); 106 | new->i_ino = pinfo->pi_stat.st_ino; 107 | new->i_flag = 0; 108 | 109 | new->i_next = *cur; 110 | *cur = new; 111 | 112 | return( NULL ); 113 | 114 | } 115 | 116 | void 117 | hardlink_free( ) 118 | { 119 | struct devlist *dev_next; 120 | struct inolist *ino_head, *ino_next; 121 | 122 | while ( dev_head != NULL ) { 123 | dev_next = dev_head->d_next; 124 | ino_head = dev_head->d_ilist; 125 | while ( ino_head != NULL ) { 126 | ino_next = ino_head->i_next; 127 | free( ino_head->i_name); 128 | free( ino_head ); 129 | ino_head = ino_next; 130 | } 131 | free( dev_head ); 132 | dev_head = dev_next; 133 | } 134 | } 135 | 136 | int 137 | hardlink_changed( struct pathinfo *pinfo, int set ) 138 | { 139 | struct devlist *dcur; 140 | struct inolist *icur; 141 | 142 | for ( dcur = dev_head; dcur != NULL; dcur = dcur->d_next ) { 143 | if ( pinfo->pi_stat.st_dev <= dcur->d_dev ) { 144 | break; 145 | } 146 | } 147 | 148 | if (( dcur == NULL ) || ( pinfo->pi_stat.st_dev != dcur->d_dev )) { 149 | fprintf( stderr, "hardlink_changed: %s: dev not found\n", 150 | pinfo->pi_name ); 151 | exit( 2 ); 152 | } 153 | 154 | for ( icur = dcur->d_ilist; icur != NULL; icur = icur->i_next ) { 155 | if ( pinfo->pi_stat.st_ino <= icur->i_ino ) { 156 | break; 157 | } 158 | } 159 | 160 | if (( icur == NULL ) || ( pinfo->pi_stat.st_ino != icur->i_ino )) { 161 | fprintf( stderr, "hardlink_changed: %s: ino not found\n", 162 | pinfo->pi_name ); 163 | exit( 2 ); 164 | } 165 | 166 | if ( set ) { 167 | icur->i_flag = 1; 168 | } 169 | 170 | return( icur->i_flag ); 171 | } 172 | -------------------------------------------------------------------------------- /install-sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # install - install a program, script, or datafile 4 | # This comes from X11R5 (mit/util/scripts/install.sh). 5 | # 6 | # Copyright 1991 by the Massachusetts Institute of Technology 7 | # 8 | # Permission to use, copy, modify, distribute, and sell this software and its 9 | # documentation for any purpose is hereby granted without fee, provided that 10 | # the above copyright notice appear in all copies and that both that 11 | # copyright notice and this permission notice appear in supporting 12 | # documentation, and that the name of M.I.T. not be used in advertising or 13 | # publicity pertaining to distribution of the software without specific, 14 | # written prior permission. M.I.T. makes no representations about the 15 | # suitability of this software for any purpose. It is provided "as is" 16 | # without express or implied warranty. 17 | # 18 | # Calling this script install-sh is preferred over install.sh, to prevent 19 | # `make' implicit rules from creating a file called install from it 20 | # when there is no Makefile. 21 | # 22 | # This script is compatible with the BSD install script, but was written 23 | # from scratch. It can only install one file at a time, a restriction 24 | # shared with many OS's install programs. 25 | 26 | 27 | # set DOITPROG to echo to test this script 28 | 29 | # Don't use :- since 4.3BSD and earlier shells don't like it. 30 | doit="${DOITPROG-}" 31 | 32 | 33 | # put in absolute paths if you don't have them in your path; or use env. vars. 34 | 35 | mvprog="${MVPROG-mv}" 36 | cpprog="${CPPROG-cp}" 37 | chmodprog="${CHMODPROG-chmod}" 38 | chownprog="${CHOWNPROG-chown}" 39 | chgrpprog="${CHGRPPROG-chgrp}" 40 | stripprog="${STRIPPROG-strip}" 41 | rmprog="${RMPROG-rm}" 42 | mkdirprog="${MKDIRPROG-mkdir}" 43 | 44 | transformbasename="" 45 | transform_arg="" 46 | instcmd="$mvprog" 47 | chmodcmd="$chmodprog 0755" 48 | chowncmd="" 49 | chgrpcmd="" 50 | stripcmd="" 51 | rmcmd="$rmprog -f" 52 | mvcmd="$mvprog" 53 | src="" 54 | dst="" 55 | dir_arg="" 56 | 57 | while [ x"$1" != x ]; do 58 | case $1 in 59 | -c) instcmd="$cpprog" 60 | shift 61 | continue;; 62 | 63 | -d) dir_arg=true 64 | shift 65 | continue;; 66 | 67 | -m) chmodcmd="$chmodprog $2" 68 | shift 69 | shift 70 | continue;; 71 | 72 | -o) chowncmd="$chownprog $2" 73 | shift 74 | shift 75 | continue;; 76 | 77 | -g) chgrpcmd="$chgrpprog $2" 78 | shift 79 | shift 80 | continue;; 81 | 82 | -s) stripcmd="$stripprog" 83 | shift 84 | continue;; 85 | 86 | -t=*) transformarg=`echo $1 | sed 's/-t=//'` 87 | shift 88 | continue;; 89 | 90 | -b=*) transformbasename=`echo $1 | sed 's/-b=//'` 91 | shift 92 | continue;; 93 | 94 | *) if [ x"$src" = x ] 95 | then 96 | src=$1 97 | else 98 | # this colon is to work around a 386BSD /bin/sh bug 99 | : 100 | dst=$1 101 | fi 102 | shift 103 | continue;; 104 | esac 105 | done 106 | 107 | if [ x"$src" = x ] 108 | then 109 | echo "install: no input file specified" 110 | exit 1 111 | else 112 | : 113 | fi 114 | 115 | if [ x"$dir_arg" != x ]; then 116 | dst=$src 117 | src="" 118 | 119 | if [ -d $dst ]; then 120 | instcmd=: 121 | chmodcmd="" 122 | else 123 | instcmd=$mkdirprog 124 | fi 125 | else 126 | 127 | # Waiting for this to be detected by the "$instcmd $src $dsttmp" command 128 | # might cause directories to be created, which would be especially bad 129 | # if $src (and thus $dsttmp) contains '*'. 130 | 131 | if [ -f $src -o -d $src ] 132 | then 133 | : 134 | else 135 | echo "install: $src does not exist" 136 | exit 1 137 | fi 138 | 139 | if [ x"$dst" = x ] 140 | then 141 | echo "install: no destination specified" 142 | exit 1 143 | else 144 | : 145 | fi 146 | 147 | # If destination is a directory, append the input filename; if your system 148 | # does not like double slashes in filenames, you may need to add some logic 149 | 150 | if [ -d $dst ] 151 | then 152 | dst="$dst"/`basename $src` 153 | else 154 | : 155 | fi 156 | fi 157 | 158 | ## this sed command emulates the dirname command 159 | dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` 160 | 161 | # Make sure that the destination directory exists. 162 | # this part is taken from Noah Friedman's mkinstalldirs script 163 | 164 | # Skip lots of stat calls in the usual case. 165 | if [ ! -d "$dstdir" ]; then 166 | defaultIFS=' 167 | ' 168 | IFS="${IFS-${defaultIFS}}" 169 | 170 | oIFS="${IFS}" 171 | # Some sh's can't handle IFS=/ for some reason. 172 | IFS='%' 173 | set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` 174 | IFS="${oIFS}" 175 | 176 | pathcomp='' 177 | 178 | while [ $# -ne 0 ] ; do 179 | pathcomp="${pathcomp}${1}" 180 | shift 181 | 182 | if [ ! -d "${pathcomp}" ] ; 183 | then 184 | $mkdirprog "${pathcomp}" 185 | else 186 | : 187 | fi 188 | 189 | pathcomp="${pathcomp}/" 190 | done 191 | fi 192 | 193 | if [ x"$dir_arg" != x ] 194 | then 195 | $doit $instcmd $dst && 196 | 197 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else : ; fi && 198 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else : ; fi && 199 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else : ; fi && 200 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else : ; fi 201 | else 202 | 203 | # If we're going to rename the final executable, determine the name now. 204 | 205 | if [ x"$transformarg" = x ] 206 | then 207 | dstfile=`basename $dst` 208 | else 209 | dstfile=`basename $dst $transformbasename | 210 | sed $transformarg`$transformbasename 211 | fi 212 | 213 | # don't allow the sed command to completely eliminate the filename 214 | 215 | if [ x"$dstfile" = x ] 216 | then 217 | dstfile=`basename $dst` 218 | else 219 | : 220 | fi 221 | 222 | # Make a temp file name in the proper directory. 223 | 224 | dsttmp=$dstdir/#inst.$$# 225 | 226 | # Move or copy the file name to the temp name 227 | 228 | $doit $instcmd $src $dsttmp && 229 | 230 | trap "rm -f ${dsttmp}" 0 && 231 | 232 | # and set any options; do chmod last to preserve setuid bits 233 | 234 | # If any of these fail, we abort the whole thing. If we want to 235 | # ignore errors from any of these, just make sure not to ignore 236 | # errors from the above "$doit $instcmd $src $dsttmp" command. 237 | 238 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else :;fi && 239 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else :;fi && 240 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else :;fi && 241 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else :;fi && 242 | 243 | # Now rename the file to the real destination. 244 | 245 | $doit $rmcmd -f $dstdir/$dstfile && 246 | $doit $mvcmd $dsttmp $dstdir/$dstfile 247 | 248 | fi && 249 | 250 | 251 | exit 0 252 | -------------------------------------------------------------------------------- /largefile.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | #ifndef SIZEOF_OFF_T 7 | #error "sizeof off_t unknown." 8 | #endif 9 | 10 | #if SIZEOF_OFF_T == 8 11 | #ifdef HAVE_STRTOLL 12 | #define strtoofft(x,y,z) (strtoll((x),(y),(z))) 13 | #else 14 | #define strtoofft(x,y,z) (strtol((x),(y),(z))) 15 | #endif 16 | #define PRIofft "ll" 17 | #else /* a bit of an assumption, here */ 18 | #define strtoofft(x,y,z) (strtol((x),(y),(z))) 19 | #define PRIofft "l" 20 | #endif 21 | 22 | #if SIZEOF_TIME_T == 8 23 | #ifdef HAVE_STRTOLL 24 | #define strtotimet(x,y,z) (strtoll((x),(y),(z))) 25 | #else /* !HAVE_STRTOLL */ 26 | #define strtotimet(x,y,z) (strtol((x),(y),(z))) 27 | #endif /* HAVE_STRTOLL */ 28 | #define PRItimet "ll" 29 | #else /* SIZEOF_TIME_T != 8 */ 30 | #define strtotimet(x,y,z) (strtol((x),(y),(z))) 31 | #define PRItimet "l" 32 | #endif /* SIZEOF_TIME_T */ 33 | -------------------------------------------------------------------------------- /list.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "list.h" 15 | #include "pathcmp.h" 16 | 17 | struct node * _list_create_node( char *path ); 18 | 19 | struct node * 20 | _list_create_node( char *path ) 21 | { 22 | struct node *new_node; 23 | 24 | if ( strlen( path ) >= MAXPATHLEN ) { 25 | errno = ENAMETOOLONG; 26 | return( NULL ); 27 | } 28 | 29 | if (( new_node = (struct node *) malloc( sizeof( struct node ))) == NULL ) { 30 | return( NULL ); 31 | } 32 | memset( new_node, 0, sizeof( struct node )); 33 | sprintf( new_node->n_path, "%s", path ); 34 | 35 | return( new_node ); 36 | } 37 | 38 | struct list * 39 | list_new( void ) 40 | { 41 | struct list *list; 42 | 43 | if (( list = malloc( sizeof( struct list ))) == NULL ) { 44 | return( NULL ); 45 | } 46 | 47 | memset( list, 0, sizeof( struct list )); 48 | return( list ); 49 | } 50 | 51 | void 52 | list_clear( struct list *list ) 53 | { 54 | /* Remove items from tail of list */ 55 | while ( list->l_tail != NULL ) { 56 | list_remove_tail( list ); 57 | } 58 | } 59 | 60 | void 61 | list_free( struct list *list ) 62 | { 63 | list_clear( list ); 64 | free( list ); 65 | } 66 | 67 | void 68 | list_print( struct list *list ) 69 | { 70 | struct node *cur; 71 | u_int i; 72 | 73 | printf( "count: %d\n", list->l_count ); 74 | for ( cur = list->l_head, i = 1; cur != NULL; cur = cur->n_next, i++ ) { 75 | printf( "%d: %s ( prev %s next %s )\n", i, cur->n_path, 76 | cur->n_prev ? cur->n_prev->n_path : "NULL", 77 | cur->n_next ? cur->n_next->n_path : "NULL" ); 78 | } 79 | printf( "\n" ); 80 | } 81 | 82 | int 83 | list_insert_case( struct list *list, char *path, int case_sensitive ) 84 | { 85 | struct node *new_node, *cur; 86 | 87 | for ( cur = list->l_head; cur != NULL; cur = cur->n_next ) { 88 | if ( pathcasecmp( cur->n_path, path, case_sensitive ) > 0 ) { 89 | break; 90 | } 91 | } 92 | 93 | /* Insert at tail or into empty list */ 94 | if ( cur == NULL ) { 95 | return( list_insert_tail( list, path )); 96 | } 97 | 98 | /* Insert at head */ 99 | if ( cur->n_prev == NULL ) { 100 | return( list_insert_head( list, path )); 101 | } 102 | 103 | /* Insert in middle */ 104 | if (( new_node = _list_create_node( path )) == NULL ) { 105 | return( -1 ); 106 | } 107 | new_node->n_next = cur; 108 | cur->n_prev->n_next = new_node; 109 | new_node->n_prev = cur->n_prev; 110 | cur->n_prev = new_node; 111 | 112 | list->l_count++; 113 | return( 0 ); 114 | } 115 | 116 | int 117 | list_insert( struct list *list, char *path ) 118 | { 119 | return( list_insert_case( list, path, 1 )); 120 | } 121 | 122 | int 123 | list_insert_head( struct list *list, char *path ) 124 | { 125 | struct node *new_node; 126 | 127 | if (( new_node = _list_create_node( path )) == NULL ) { 128 | return( -1 ); 129 | } 130 | 131 | if ( list->l_head == NULL ) { 132 | list->l_tail = new_node; 133 | } else { 134 | list->l_head->n_prev = new_node; 135 | new_node->n_next = list->l_head; 136 | } 137 | list->l_head = new_node; 138 | 139 | list->l_count++; 140 | return( 0 ); 141 | } 142 | 143 | int 144 | list_insert_tail( struct list *list, char *path ) 145 | { 146 | struct node *new_node; 147 | 148 | if (( new_node = _list_create_node( path )) == NULL ) { 149 | return( -1 ); 150 | } 151 | 152 | if ( list->l_tail == NULL ) { 153 | list->l_head = new_node; 154 | } else { 155 | list->l_tail->n_next = new_node; 156 | new_node->n_prev = list->l_tail; 157 | } 158 | list->l_tail = new_node; 159 | 160 | list->l_count++; 161 | return( 0 ); 162 | } 163 | 164 | int 165 | list_remove( struct list *list, char *path ) 166 | { 167 | int count = 0; 168 | struct node *cur; 169 | 170 | for ( cur = list->l_head; cur != NULL; cur = cur->n_next ) { 171 | if ( pathcmp( cur->n_path, path ) == 0 ) { 172 | 173 | if ( list->l_head == cur ) { 174 | list_remove_head( list ); 175 | count++; 176 | 177 | } else if ( list->l_tail == cur ) { 178 | list_remove_tail( list ); 179 | count++; 180 | 181 | } else { 182 | /* Remove item */ 183 | cur->n_prev->n_next = cur->n_next; 184 | cur->n_next->n_prev = cur->n_prev; 185 | free( cur ); 186 | list->l_count--; 187 | count++; 188 | } 189 | } 190 | } 191 | 192 | return( count ); 193 | } 194 | 195 | void 196 | list_remove_tail( struct list *list ) 197 | { 198 | struct node *node; 199 | 200 | if (( node = list_pop_tail( list )) != NULL ) { 201 | free( node ); 202 | } 203 | } 204 | 205 | struct node * 206 | list_pop_tail( struct list * list ) 207 | { 208 | struct node *node; 209 | 210 | if ( list->l_tail == NULL ) { 211 | return( NULL ); 212 | } 213 | node = list->l_tail; 214 | if ( list->l_count == 1 ) { 215 | list->l_tail = NULL; 216 | list->l_head = NULL; 217 | } else { 218 | list->l_tail = list->l_tail->n_prev; 219 | list->l_tail->n_next = NULL; 220 | } 221 | list->l_count--; 222 | return( node ); 223 | } 224 | 225 | void 226 | list_remove_head( struct list *list ) 227 | { 228 | struct node *node; 229 | 230 | if (( node = list_pop_head( list )) != NULL ) { 231 | free( node ); 232 | } 233 | } 234 | 235 | struct node * 236 | list_pop_head( struct list *list ) 237 | { 238 | struct node *node; 239 | 240 | if ( list->l_head == NULL ) { 241 | return( NULL ); 242 | } 243 | node = list->l_head; 244 | if ( list->l_count == 1 ) { 245 | list->l_tail = NULL; 246 | list->l_head = NULL; 247 | } 248 | if ( list->l_head != NULL ) { 249 | list->l_head = list->l_head->n_next; 250 | list->l_head->n_prev = NULL; 251 | } 252 | list->l_count--; 253 | return( node ); 254 | } 255 | 256 | int 257 | list_check( struct list *list, char *path ) 258 | { 259 | struct node *cur; 260 | 261 | for ( cur = list->l_head; cur != NULL; cur = cur->n_next ) { 262 | if ( pathcmp( cur->n_path, path ) == 0 ) { 263 | return( 1 ); 264 | } 265 | } 266 | 267 | return( 0 ); 268 | } 269 | -------------------------------------------------------------------------------- /list.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | struct list 7 | { 8 | int l_count; 9 | struct node *l_head; 10 | struct node *l_tail; 11 | }; 12 | 13 | struct node 14 | { 15 | char n_path[ MAXPATHLEN ]; 16 | struct node *n_next; 17 | struct node *n_prev; 18 | }; 19 | 20 | #define list_size( list ) ((list) ? (list)->l_count : 0 ) 21 | 22 | struct list * list_new( void ); 23 | void list_clear( struct list *list ); 24 | void list_free( struct list *list ); 25 | void list_print( struct list *list ); 26 | int list_insert( struct list *list, char *path ); 27 | int list_insert_case( struct list *list, char *path, 28 | int case_sensitive ); 29 | int list_insert_head( struct list *list, char *path ); 30 | int list_insert_tail( struct list *list, char *path ); 31 | int list_remove( struct list *list, char *path ); 32 | void list_remove_head( struct list *list ); 33 | void list_remove_tail( struct list *list ); 34 | struct node * list_pop_head( struct list *list ); 35 | struct node * list_pop_tail( struct list *list ); 36 | int list_check( struct list *list, char *path ); 37 | int list_check_case( struct list *list, char *path ); 38 | -------------------------------------------------------------------------------- /llist.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "applefile.h" 14 | #include "transcript.h" 15 | #include "llist.h" 16 | 17 | /* Allocate a new list node */ 18 | struct llist * 19 | ll_allocate( char *name ) 20 | { 21 | struct llist *new; 22 | 23 | /* allocate space for next item in list */ 24 | if (( new = (struct llist *)malloc( sizeof( struct llist ))) == NULL ) { 25 | perror( "malloc" ); 26 | exit( 2 ); 27 | } 28 | 29 | /* copy info into new item */ 30 | strcpy( new->ll_name, name ); 31 | new->ll_next = NULL; 32 | 33 | return new; 34 | } 35 | 36 | /* Free the whole list */ 37 | void 38 | ll_free( struct llist *head ) 39 | { 40 | struct llist *next; 41 | 42 | for ( ; head != NULL; head = next ) { 43 | next = head->ll_next; 44 | free( head ); 45 | } 46 | } 47 | 48 | void 49 | ll_insert( struct llist **headp, struct llist *new ) 50 | { 51 | struct llist **current; 52 | 53 | /* find where in the list to put the new entry */ 54 | for ( current = headp; *current != NULL; current = &(*current)->ll_next) { 55 | if ( strcmp( new->ll_name, (*current)->ll_name ) <= 0 ) { 56 | break; 57 | } 58 | } 59 | 60 | new->ll_next = *current; 61 | *current = new; 62 | return; 63 | } 64 | 65 | /* Insert a new node into the list */ 66 | void 67 | ll_insert_case( struct llist **headp, struct llist *new ) 68 | { 69 | struct llist **current; 70 | 71 | /* find where in the list to put the new entry */ 72 | for ( current = headp; *current != NULL; current = &(*current)->ll_next) { 73 | if ( strcasecmp( new->ll_name, (*current)->ll_name ) <= 0 ) { 74 | break; 75 | } 76 | } 77 | 78 | new->ll_next = *current; 79 | *current = new; 80 | return; 81 | } 82 | -------------------------------------------------------------------------------- /llist.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | struct llist { 7 | char ll_name[ MAXPATHLEN ]; 8 | struct llist *ll_next; 9 | }; 10 | 11 | struct llist * ll_allocate( char * ); 12 | void ll_free( struct llist * ); 13 | void ll_insert( struct llist **, struct llist * ); 14 | void ll_insert_case( struct llist **, struct llist * ); 15 | -------------------------------------------------------------------------------- /lmerge.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | struct tran 7 | { 8 | int num; 9 | int eof; 10 | int tac; 11 | int remove; 12 | int linenum; 13 | char *path; 14 | char *name; 15 | char *line; 16 | char tline[ 2 * MAXPATHLEN ]; 17 | char prepath[ MAXPATHLEN ]; 18 | char filepath[ MAXPATHLEN ]; 19 | char **targv; 20 | FILE *fs; 21 | ACAV *acav; 22 | struct node *next; 23 | }; 24 | int getnextline( struct tran *tran ); 25 | -------------------------------------------------------------------------------- /logname.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | 11 | #include "logname.h" 12 | 13 | struct syslogname _sysloglevel[] = { 14 | { "emerg", LOG_EMERG }, 15 | { "alert", LOG_ALERT }, 16 | { "crit", LOG_CRIT }, 17 | { "err", LOG_ERR }, 18 | { "warning", LOG_WARNING }, 19 | { "notice", LOG_NOTICE }, 20 | { "info", LOG_INFO }, 21 | { "debug", LOG_DEBUG }, 22 | { 0, 0 }, 23 | }; 24 | 25 | struct syslogname _syslogfacility[] = { 26 | #ifdef LOG_KERN 27 | { "kern", LOG_KERN }, 28 | #endif // LOG_KERN 29 | { "user", LOG_USER }, 30 | { "mail", LOG_MAIL }, 31 | { "daemon", LOG_DAEMON }, 32 | { "auth", LOG_AUTH }, 33 | { "syslog", LOG_SYSLOG }, 34 | { "lpr", LOG_LPR }, 35 | { "news", LOG_NEWS }, 36 | { "uucp", LOG_UUCP }, 37 | { "cron", LOG_CRON }, 38 | #ifdef LOG_FTP 39 | { "ftp", LOG_FTP }, 40 | #endif // LOG_FTP 41 | #ifdef LOG_AUTHPRIV 42 | { "authpriv", LOG_AUTHPRIV }, 43 | #endif // LOG_AUTHPRIV 44 | { "local0", LOG_LOCAL0 }, 45 | { "local1", LOG_LOCAL1 }, 46 | { "local2", LOG_LOCAL2 }, 47 | { "local3", LOG_LOCAL3 }, 48 | { "local4", LOG_LOCAL4 }, 49 | { "local5", LOG_LOCAL5 }, 50 | { "local6", LOG_LOCAL6 }, 51 | { "local7", LOG_LOCAL7 }, 52 | { 0, 0 }, 53 | }; 54 | 55 | int 56 | syslogname( char *name, struct syslogname *sln ) 57 | { 58 | for ( ; sln->sl_name != 0; sln++ ) { 59 | if ( strcasecmp( sln->sl_name, name ) == 0 ) { 60 | return( sln->sl_value ); 61 | } 62 | } 63 | return( -1 ); 64 | } 65 | -------------------------------------------------------------------------------- /logname.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | struct syslogname { 6 | char *sl_name; 7 | int sl_value; 8 | }; 9 | 10 | extern struct syslogname _syslogfacility[], _sysloglevel[]; 11 | int syslogname( char *, struct syslogname * ); 12 | 13 | #define syslogfacility(x) syslogname((x),_syslogfacility) 14 | #define sysloglevel(x) syslogname((x),_sysloglevel) 15 | -------------------------------------------------------------------------------- /lsize.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "argcargv.h" 13 | #include "list.h" 14 | 15 | #define K_CLIENT 0 16 | #define K_SERVER 1 17 | 18 | extern int errno; 19 | 20 | off_t lsize( char *tpath ); 21 | off_t kfile_size( char *kfile, int location ); 22 | 23 | static struct list *kfile_list; 24 | static char kdir[ MAXPATHLEN ]; 25 | 26 | off_t 27 | lsize( char *tpath ) 28 | { 29 | FILE *tfp = NULL; 30 | unsigned long long totalsize = 0, cursize = 0; 31 | char **tav = NULL; 32 | char line[ MAXPATHLEN * 2 ]; 33 | int tac, linenum = 1; 34 | 35 | if (( tfp = fopen( tpath, "r" )) == NULL ) { 36 | fprintf( stderr, "fopen %s: %s\n", tpath, strerror( errno )); 37 | exit( 2 ); 38 | } 39 | 40 | while ( fgets( line, MAXPATHLEN * 2, tfp ) != NULL ) { 41 | linenum++; 42 | if (( tac = argcargv( line, &tav )) != 8 ) { 43 | continue; 44 | } 45 | 46 | if ( *tav[ 0 ] != 'a' && *tav[ 0 ] != 'f' ) { 47 | continue; 48 | } 49 | 50 | /* XXX - use strtoofft */ 51 | cursize = strtoull( tav[ 6 ], NULL, 10 ); 52 | if ( errno == ERANGE || errno == EINVAL ) { 53 | fprintf( stderr, "line %d: strtoull %s: %s\n", 54 | linenum, tav[ 6 ], strerror( errno )); 55 | exit( 2 ); 56 | } 57 | 58 | totalsize += cursize; 59 | } 60 | 61 | ( void )fclose( tfp ); 62 | 63 | return( totalsize ); 64 | } 65 | 66 | off_t 67 | kfile_size( char *kfile, int location ) 68 | { 69 | FILE *fp; 70 | off_t cursize = 0, total = 0; 71 | int length, ac, linenum = 0; 72 | char line[ MAXPATHLEN ]; 73 | char fullpath[ MAXPATHLEN ]; 74 | char *subpath; 75 | char **av; 76 | 77 | if (( fp = fopen( kfile, "r" )) == NULL ) { 78 | perror( kfile ); 79 | return( -1 ); 80 | } 81 | 82 | while ( fgets( line, sizeof( line ), fp ) != NULL ) { 83 | linenum++; 84 | length = strlen( line ); 85 | if ( line[ length - 1 ] != '\n' ) { 86 | fprintf( stderr, "command: line %d: line too long\n", linenum ); 87 | return( -1 ); 88 | } 89 | 90 | /* skips blank lines and comments */ 91 | if ((( ac = argcargv( line, &av )) == 0 ) || ( *av[ 0 ] == '#' )) { 92 | continue; 93 | } 94 | 95 | if ( ac != 2 ) { 96 | fprintf( stderr, "command: line %d: expected 2 arguments, got %d\n", 97 | linenum, ac ); 98 | return( -1 ); 99 | } 100 | 101 | switch( location ) { 102 | case K_CLIENT: 103 | if ( snprintf( fullpath, MAXPATHLEN, "%s%s", kdir, 104 | av[ 1 ] ) >= MAXPATHLEN ) { 105 | fprintf( stderr, "command: line %d: path too long\n", 106 | linenum ); 107 | fprintf( stderr, "command: line %d: %s%s\n", 108 | linenum, kdir, av[ 1 ] ); 109 | return( -1 ); 110 | } 111 | break; 112 | 113 | case K_SERVER: 114 | if ( *av[ 0 ] == 'k' ) { 115 | subpath = "command"; 116 | } else { 117 | subpath = "transcript"; 118 | } 119 | if ( snprintf( fullpath, MAXPATHLEN, "%s/%s/%s", _RADMIND_PATH, 120 | subpath, av[ 1 ] ) >= MAXPATHLEN ) { 121 | fprintf( stderr, "command: line %d: path too long\n", 122 | linenum ); 123 | fprintf( stderr, "command: line %d: %s%s\n", 124 | linenum, kdir, av[ 1 ] ); 125 | return( -1 ); 126 | } 127 | break; 128 | 129 | default: 130 | fprintf( stderr, "unknown location\n" ); 131 | return( -1 ); 132 | } 133 | 134 | switch( *av[ 0 ] ) { 135 | case 'k': /* command file */ 136 | if ( list_check( kfile_list, fullpath )) { 137 | fprintf( stderr, 138 | "%s: line %d: command file loop: %s already included\n", 139 | kfile, linenum, av[ 1 ] ); 140 | return( -1 ); 141 | } 142 | if ( list_insert( kfile_list, fullpath ) != 0 ) { 143 | perror( "list_insert" ); 144 | return( -1 ); 145 | } 146 | 147 | if (( cursize = kfile_size( fullpath, location )) < 0 ) { 148 | return( -1 ); 149 | } 150 | total += cursize; 151 | break; 152 | 153 | case 'n': /* negative */ 154 | /* XXX - include sizes from negative? */ 155 | continue; 156 | 157 | case 'p': /* positive */ 158 | total += lsize( fullpath ); 159 | break; 160 | 161 | case 's': /* special */ 162 | /* XXX - provide -h option to indicate client? */ 163 | continue; 164 | 165 | default: 166 | fprintf( stderr, "command: line %d: '%s' invalid\n", 167 | linenum, av[ 0 ] ); 168 | return( -1 ); 169 | } 170 | } 171 | 172 | if ( fclose( fp ) != 0 ) { 173 | perror( kfile ); 174 | return( -1 ); 175 | } 176 | 177 | return( total ); 178 | } 179 | 180 | int 181 | main( int ac, char *av[] ) 182 | { 183 | char *path = NULL, *ext = NULL, *p; 184 | double totalsize = 0; 185 | int c, factor = 1024, err = 0, kfile = 0; 186 | extern int optind; 187 | 188 | while (( c = getopt( ac, av, "bgkm" )) != EOF ) { 189 | switch ( c ) { 190 | case 'b': /* bytes */ 191 | factor = 1; 192 | break; 193 | 194 | case 'g': /* gigabytes */ 195 | factor = ( 1024 * 1024 * 1024 ); 196 | break; 197 | 198 | case 'k': /* kilobytes (default) */ 199 | factor = 1024; 200 | break; 201 | 202 | case 'm': /* megabytes */ 203 | factor = ( 1024 * 1024 ); 204 | break; 205 | 206 | case '?': 207 | err++; 208 | } 209 | } 210 | 211 | path = av[ optind ]; 212 | 213 | if ( err || ( ac - optind ) != 1 ) { 214 | fprintf( stderr, "Usage: %s [ -bgkmt ] { commandfile " 215 | "| transcript }\n", av[ 0 ] ); 216 | exit( 1 ); 217 | } 218 | 219 | if (( ext = strrchr( path, '.' )) != NULL ) { 220 | if ( strcmp( ++ext, "K" ) == 0 ) { 221 | kfile = 1; 222 | if ( strlen( path ) >= MAXPATHLEN ) { 223 | fprintf( stderr, "%s: path too long\n", path ); 224 | exit( 2 ); 225 | } 226 | strcpy( kdir, path ); 227 | 228 | if (( p = strrchr( kdir, '/' )) == NULL ) { 229 | /* use working directory */ 230 | strcpy( kdir, "./" ); 231 | } else { 232 | p++; 233 | *p = (char)'\0'; 234 | } 235 | if (( kfile_list = list_new()) == NULL ) { 236 | perror( "list_new" ); 237 | exit( 2 ); 238 | } 239 | if ( list_insert( kfile_list, path ) != 0 ) { 240 | perror( "list_insert" ); 241 | exit( 2 ); 242 | } 243 | } 244 | /* otherwise assume it's a transcript */ 245 | } 246 | 247 | if ( kfile ) { 248 | if (( totalsize = ( double )kfile_size( path, K_SERVER )) < 0 ) { 249 | exit( 2 ); 250 | } 251 | } else { 252 | totalsize = ( double )lsize( path ); 253 | } 254 | 255 | totalsize /= ( double )factor; 256 | 257 | printf( "%.2f\n", totalsize ); 258 | 259 | return( 0 ); 260 | } 261 | -------------------------------------------------------------------------------- /lsort.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "argcargv.h" 13 | #include "code.h" 14 | #include "pathcmp.h" 15 | 16 | int linecount; 17 | FILE *outtran; 18 | 19 | struct save_line { 20 | struct save_line *next; 21 | char *key; 22 | char *data; 23 | } *lines; 24 | 25 | void save_it( char *buffer, char *pathname ); 26 | static int lsort_cmp( const void *a1, const void *b1 ); 27 | void sort_them( void ); 28 | void print_them( void ); 29 | void process( char * arg ); 30 | 31 | int case_sensitive = 1; 32 | 33 | void 34 | save_it( char *buffer, char *pathname ) 35 | { 36 | struct save_line *sp; 37 | 38 | sp = malloc( sizeof( *sp ) + strlen( buffer ) + strlen( pathname ) + 4 ); 39 | sp->key = (char*)( sp + 1 ); 40 | strcpy( sp->key, pathname ); 41 | sp->data = ( sp->key + strlen( sp->key ) + 1 ); 42 | strcpy( sp->data, buffer ); 43 | sp->next = lines; 44 | lines = sp; 45 | linecount++; 46 | } 47 | 48 | static int 49 | lsort_cmp( const void *a1, const void *b1 ) 50 | { 51 | const struct save_line **a, **b; 52 | 53 | a = (const struct save_line**)a1; 54 | b = (const struct save_line**)b1; 55 | 56 | return( pathcasecmp((*a)->key, (*b)->key, case_sensitive )); 57 | } 58 | 59 | void 60 | sort_them( void ) 61 | { 62 | struct save_line **x, *sp, **y; 63 | 64 | x = (struct save_line**) malloc( sizeof( *x ) * linecount ); 65 | y = x; 66 | 67 | for ( sp = lines; sp; sp = sp->next ) { 68 | *y++ = sp; 69 | } 70 | 71 | qsort( x, linecount, sizeof *x, lsort_cmp ); 72 | 73 | sp = 0; 74 | while ( y-- != x ) { 75 | (*y)->next = sp; 76 | sp = (*y); 77 | } 78 | 79 | lines = sp; 80 | } 81 | 82 | void 83 | print_them( void ) 84 | { 85 | struct save_line *sp; 86 | for ( sp = lines; sp; sp = sp->next ) { 87 | fputs( sp->data, outtran ); 88 | if ( ferror( outtran )) { 89 | perror( "fputs" ); 90 | exit( 2 ); 91 | } 92 | } 93 | } 94 | 95 | void 96 | process( char *arg ) 97 | { 98 | FILE *f; 99 | ACAV *acav; 100 | char buffer[4096]; 101 | char *fn; 102 | int lineno, argc; 103 | char **argv; 104 | char *line = NULL; 105 | 106 | if ( strcmp( arg, "-" )) { 107 | fn = arg; 108 | f = fopen( arg, "r" ); 109 | } else { 110 | fn = "(stdin)"; 111 | f = stdin; 112 | } 113 | if ( !f ) { 114 | perror( arg ); 115 | exit( 2 ); 116 | } 117 | 118 | acav = acav_alloc(); 119 | 120 | lineno = 0; 121 | while ( fgets( buffer, sizeof buffer, f )) { 122 | lineno++; 123 | 124 | if (( line = strdup( buffer )) == NULL ) { 125 | perror( "strdup" ); 126 | exit( 1 ); 127 | } 128 | 129 | argc = acav_parse( acav, buffer, &argv ); 130 | 131 | /* Skip blank lines */ 132 | if ( argc == 0 ) { 133 | continue; 134 | } 135 | 136 | /* XXX - Drop comments - how would you sort them? */ 137 | if ( *argv[ 0 ] == '#' ) { 138 | continue; 139 | } 140 | 141 | /* Get argument offset */ 142 | if (( *argv[ 0 ] == '+' ) || ( *argv[ 0 ] == '-' )) { 143 | argv++; 144 | argc--; 145 | } 146 | 147 | if ( argc < 2 ) { 148 | fprintf( stderr, "%s: line %d: not enough fields\n", fn, lineno ); 149 | exit( 1 ); 150 | } 151 | save_it( line, decode( argv[ 1 ] )); 152 | } 153 | 154 | if ( f == stdin ) { 155 | clearerr( f ); 156 | } else { 157 | fclose( f ); 158 | } 159 | 160 | free( line ); 161 | acav_free( acav ); 162 | } 163 | 164 | int 165 | main( int argc, char **argv ) 166 | { 167 | char c; 168 | int i, err = 0; 169 | extern char *version; 170 | 171 | outtran = stdout; 172 | 173 | while (( c = getopt( argc, argv, "Io:V" )) != EOF ) { 174 | switch( c ) { 175 | case 'I': 176 | case_sensitive = 0; 177 | break; 178 | 179 | case 'o': 180 | if (( outtran = fopen( optarg, "w" )) == NULL ) { 181 | perror( optarg ); 182 | exit( 1 ); 183 | } 184 | break; 185 | 186 | case 'V': 187 | printf( "%s\n", version ); 188 | exit( 0 ); 189 | 190 | default: 191 | err++; 192 | break; 193 | } 194 | } 195 | 196 | if ( err ) { 197 | fprintf( stderr, "Usage: %s [ -IV ] ", argv[ 0 ] ); 198 | fprintf( stderr, "[ -o file ] [ files... ]\n" ); 199 | exit( 1 ); 200 | } 201 | 202 | if ( argc - optind == 0 ) { 203 | /* Only stdin */ 204 | process( "-" ); 205 | } else { 206 | /* Process all args */ 207 | for ( i = optind; i < argc; i++ ) { 208 | if ( strcmp( argv[ i ], "-" ) == 0 ) { 209 | process( "-" ); 210 | } else { 211 | process( argv[ i ] ); 212 | } 213 | } 214 | } 215 | 216 | sort_them(); 217 | print_them(); 218 | 219 | exit( 0 ); 220 | } 221 | -------------------------------------------------------------------------------- /man/applefile.5: -------------------------------------------------------------------------------- 1 | .TH applefile "5" "_RADMIND_BUILD_DATE" "RSUG" "Headers, Environments, and Macros" 2 | .SH NAME 3 | .B applefile 4 | \- Radmind AppleSingle file 5 | .sp 6 | .SH DESCRIPTION 7 | To provide support for Mac OS X, radmind is aware of the Mac OS metadata used 8 | on HFS+-formatted drives. When 9 | .B lcreate 10 | uploads a file denoted in the transcript as an 11 | .B applefile 12 | (type 'a'), it encodes the file and the file's metadata to the server as an 13 | AppleSingle file. The AppleSingle file is an archive containing a file's 14 | relevant metadata and data in a single file stream. The radmind AppleSingle 15 | file has the following format: 16 | .sp 17 | 1) The AppleSingle header, consisting of a 18 | 4-byte magic number, 4-byte version number, 16-byte filler, 2-byte number 19 | denoting the number of entries in the archive, and 3 header entries, each 20 | describing the items in the archive and containing a 4-byte entry id, 4-byte 21 | offset, and 4-byte length; 22 | .sp 23 | 2) The file's Finder information (32 bytes), 24 | which stores 25 | the file's Type and Creator codes, as well its position in the Finder window; 26 | .sp 27 | 3) The file's Resource Fork, which contains things like images, sounds, and 28 | other data not easily or appropriately stored in the Data Fork; 29 | .sp 30 | 4) The file's 31 | Data Fork, the portion visible from the Finder, and the only part which is 32 | considered valid by flat file systems. 33 | .sp 34 | The radmind tool 35 | .B lapply 36 | similarly decodes the applefile from the server and restores it to the client 37 | Mac OS X machine running on an HFS+-formatted drive. 38 | .sp 39 | .SH MORE INFO 40 | The Apple Computer's AppleSingle RFC is available at 41 | .B http://www.faqs.org/rfcs/rfc1740.html. 42 | .sp 43 | .SH SEE ALSO 44 | .BR ktcheck (1), 45 | .BR lapply (1), 46 | .BR lcreate (1), 47 | .BR lcksum (1), 48 | .BR lfdiff (1), 49 | .BR lmerge (1), 50 | .BR lsort (1), 51 | .BR radmind (8), 52 | .BR twhich (1). 53 | -------------------------------------------------------------------------------- /man/fsdiff.1: -------------------------------------------------------------------------------- 1 | .TH fsdiff "1" "_RADMIND_BUILD_DATE" "RSUG" "User Commands" 2 | .SH NAME 3 | .B fsdiff 4 | \- compare filesystem to transcripts 5 | .SH SYNOPSIS 6 | .B fsdiff 7 | { 8 | .B -C 9 | | 10 | .B -A 11 | | 12 | .B -1 13 | } [ 14 | .BI -IVWt 15 | ] [ 16 | .BI \-K\ command 17 | ] [ 18 | .BI \-c\ checksum 19 | ] [ 20 | .BI \-o\ file 21 | [ 22 | .BI -% 23 | ] ] 24 | .I path 25 | .sp 26 | .SH DESCRIPTION 27 | .B fsdiff 28 | reads a command file (the default name is 29 | .B command.K) 30 | to get a list of transcripts. If the command file is empty, the 31 | transcript list is considered to be the null transcript. Included command files 32 | are read depth first. The first 33 | transcript listed has the lowest precedence, the 34 | next higher, and the last has the highest. 35 | If any special files are 36 | listed, the 37 | .B special.T 38 | transcript will have the absolute highest precedence. 39 | .sp 40 | .B fsdiff 41 | walks the filesystem starting at 42 | .I path 43 | and compares the filesystem to the transcripts. Trailing '/'s on 44 | .I path 45 | are clipped. 46 | .sp 47 | If a transcript is 48 | .B positive, 49 | .B fsdiff 50 | checks all attributes of each file system object 51 | ( i.e. file, directory, link, etc ). 52 | If the -c option is given, checksums are also compared. 53 | If a transcript is 54 | .B negative, 55 | .B fsdiff 56 | checks only some of the attributes of the file system objects ( see 57 | TRANSCRIPTS section below ). 58 | There is only one 59 | .B special 60 | transcript, 61 | .B special.T, 62 | and it contains references to files that are host specific, eg. 63 | /etc/hostname.hme0. 64 | .sp 65 | Any discrepancies are printed on the standard output or, with the -o option, 66 | to a file. The default is to print the differences as edits to the 67 | transcript to make it match the filesystem. If the edit direction 68 | chosen is -T or -A, the differences are printed as edits to the file system 69 | to make it match the transcript. A "+" at the beginning of a line 70 | indicates a file must be downloaded. A "-" indicates the given object ( 71 | file, directory, link etc ) must be removed. 72 | .sp 73 | .SH TRANSCRIPTS 74 | A transcript contains a list of filesystem objects, eg. directories, 75 | files, symbolic links etc. Transcripts have the following format: 76 | .sp 77 | .br 78 | type path [type specific information] 79 | .br 80 | .sp 81 | Type is a single letter: h, l, d, c, b, p, s, D, f, a. Path is the encoded 82 | path, where space is "\\b", tab is "\\t", newline is "\\n", carriage return 83 | is "\\r", and 84 | \\ is "\\\\". The type specific information varies. 85 | .sp 86 | .br 87 | l path target 88 | .br 89 | h path target 90 | .br 91 | .sp 92 | Type 'l' is a symbolic link and 'h' is a hard link. Target is encoded like 93 | path. If a symbolic link is listed in a negative transcript, the target 94 | is not checked. 95 | .sp 96 | .br 97 | d path mode uid gid [ finder-information ] 98 | .br 99 | D path mode uid gid 100 | .br 101 | s path mode uid gid 102 | .br 103 | p path mode uid gid 104 | .br 105 | .sp 106 | Type 'd' is a directory, 'D' is a door, 's' is a socket and 'p' is 107 | a named pipe. Mode is a 4 digit octal representation of the 108 | permissions. ( see 109 | .BR chmod(1). 110 | ) uid and gid are the user and group ids in decimal format. 111 | finder-information is used only on Mac OS X machines running on an 112 | HFS+ formatted drive to store directory finder information. If a 113 | directory is listed in a 114 | .B negative 115 | transcript, mode, uid, gid and, if listed, finder-information will 116 | be checked, but the directory itself will not be read. 117 | .sp 118 | .br 119 | b path mode uid gid major minor 120 | .br 121 | c path mode uid gid major minor 122 | .br 123 | .sp 124 | Type 'b' is a block special file, 'c' is a character special file. 125 | Major and minor are the major and minor device numbers in decimal. 126 | If a character special file is listed in a 127 | .B negative 128 | transcript, only major and minor device number will be checked. 129 | .sp 130 | .br 131 | f path mode uid gid mtime size checksum 132 | .br 133 | a path mode uid gid mtime size checksum 134 | .br 135 | .sp 136 | Type 'f' is a regular file. Mtime is a decimal number of seconds since 1970 GMT. 137 | Size is the size of the file in bytes. Checksum is the base64 encoded 138 | checksum if enabled, otherwise it is "-". If a file is listed in a 139 | .B negative 140 | transcript, only mode, uid and gid will be checked. 141 | .sp 142 | Type 'a' is an 143 | .B applefile, 144 | relevant only on Mac OS X machines running on an HFS+ formatted drive. 145 | An applefile 146 | has Mac OS metadata, and is stored on the server as an AppleSingle file 147 | (see applefile(5)). 148 | Everything that applies to 149 | a regular file applies to an applefile, as well. 150 | .sp 151 | Transcripts are sorted alphabetically, depth first, and case 152 | sensitively. This means subdirectories have precedence over files 153 | in the same directory: lexically, "/" has highest precedence. So 154 | the file: 155 | .sp 156 | /etc/passwd 157 | .sp 158 | comes before: 159 | .sp 160 | /etc.old 161 | .sp 162 | even though "." normally comes before "/", and: 163 | .sp 164 | /Library 165 | .sp 166 | would come before: 167 | .sp 168 | /dev 169 | .sp 170 | as capitalized characters are higher in precedence than 171 | lowercase ones. Both of the previous two directories would come 172 | before: 173 | .sp 174 | /etc.old 175 | .SH COMMAND FILES 176 | Command files have the following format: 177 | .br 178 | .sp 179 | type path 180 | .sp 181 | .br 182 | Type is 'k' for command file, 'p' for positive, 'n' for negative, 's' 183 | for special and 'x' for an exclude pattern. The 184 | argument path is either a command file name, transcript name, 185 | or in the case of type special, a full pathname. 186 | .br 187 | .br 188 | .sp 189 | # example command file 190 | .br 191 | k linux-base.K 192 | .br 193 | p test/denser-10.T 194 | .br 195 | p simta-032.T 196 | .br 197 | n simta-neg.T 198 | .br 199 | s /etc/fstab 200 | .br 201 | x /etc/tsm*.pid 202 | .sp 203 | Lines beginning with "#" are comments, and are skipped. A comment must 204 | be on a line by itself. Blank lines are also skipped. Exclude lines are 205 | wildcard patterns (see radmind(8) DESCRIPTION) of paths that will 206 | be ignored completely, that is, fsdiff will not care if an object matching 207 | an exclude line is present or absent, and will not print out anything 208 | relating to it. Exclude patterns apply to objects on the filesystem and 209 | paths in transcripts. Only special files are unaffected by excludes. For 210 | help determining which files you are excluding, use the -W flag. 211 | .sp 212 | If there is no command file, the transcript used is the null transcript. 213 | This means 214 | .B fsdiff 215 | will print out a difference line for every object in the 216 | filesystem, eg. a filesystem snapshot. 217 | .sp 218 | Positive and negative transcripts and special files can be removed from a command file by using minus lines. These lines effectively remove all previously referenced lines that match both the type and path of the minus line. Minus lines begin with a '-', followed by some amount of whitespace. 219 | .sp 220 | Minus lines only apply to transcripts and special files that have already been read from a command file. If a subsequent line or included command file lists the same transcript or special file, it will be once again included. 221 | .sp 222 | For example, if you wanted to remove the special file /etc/fstab from the previous example, you could use this command file: 223 | .br 224 | .br 225 | .sp 226 | # example command file 227 | .br 228 | k linux-base.K 229 | .br 230 | p test/denser-10.T 231 | .br 232 | p simta-032.T 233 | .br 234 | n simta-neg.T 235 | .br 236 | s /etc/fstab 237 | .br 238 | - s /etc/fstab 239 | .sp 240 | The minus line in this example would match the special file /etc/fstab, causing it to be effectively removed from the command file. 241 | .SH EXAMPLES 242 | In this example, fsdiff is used to generate a line for the negative 243 | transcript for /tmp. 244 | .sp 245 | .RS 246 | .nf 247 | example% fsdiff -1 /tmp 248 | d /tmp 1777 0 3 249 | example% 250 | .fi 251 | .RE 252 | .sp 253 | A more complete negative transcript might look like this: 254 | .sp 255 | .RS 256 | .nf 257 | example% vi negative.T 258 | f /etc/passwd 0444 0 3 993477914 482 - 259 | d /proc 0555 0 0 260 | d /tmp 1777 0 3 261 | f /var/adm/lastlog 0444 0 1 993662219 976304 - 262 | f /var/adm/messages 0644 0 0 993661335 94910 - 263 | f /var/adm/sulog 0600 0 0 993662246 422 - 264 | f /var/adm/utmpx 0644 0 2 993662219 2604 - 265 | f /var/adm/wtmpx 0644 4 4 993662219 111600 - 266 | f /var/cron/log 0600 0 0 993627000 2694 - 267 | d /xfn 0555 0 0 268 | .fi 269 | .RE 270 | .sp 271 | .SH OPTIONS 272 | .TP 19 273 | .B \-% 274 | percentage done progress output. Requires -o option. 275 | .TP 19 276 | .B no option 277 | fsdiff defaults to -A. Future releases will require an option explicitly. 278 | .TP 19 279 | .B \-1 280 | prints out a single transcript line for the given file. This option can be 281 | used to build 282 | .B negative 283 | transcripts. 284 | .TP 19 285 | .B \-A 286 | produces an applicable transcript. 287 | .TP 19 288 | .B \-C 289 | produces a creatable transcript. 290 | .TP 19 291 | .BI \-c\ checksum 292 | enables checksuming. 293 | .TP 19 294 | .BI \-I 295 | be case insensitive when compairing paths. 296 | .TP 19 297 | .BI \-K\ command 298 | specifies a command 299 | file name, by default 300 | .B _RADMIND_COMMANDFILE 301 | .TP 19 302 | .BI \-o\ file 303 | specifies an output file, default is the standard output. 304 | .TP 19 305 | .B \-V 306 | displays the version number of 307 | .BR fsdiff , 308 | a list of supported checksumming algorithms in descending 309 | order of preference and then exits. 310 | .TP 19 311 | .B \-W 312 | prints a warning to the standard error when encountering an object 313 | matching an exclude pattern. 314 | .sp 315 | .TP 19 316 | .B \-t 317 | ignores files where only the timestamp has changed. 318 | .SH FILES 319 | .TP 19 320 | .B _RADMIND_COMMANDFILE 321 | name of the default command file. 322 | .TP 19 323 | .B special.T 324 | name of the special transcript. 325 | .sp 326 | .SH EXIT STATUS 327 | The following exit values are returned: 328 | .TP 5 329 | 0 330 | No errors. 331 | .TP 5 332 | >1 333 | An error occurred. 334 | .sp 335 | .SH SEE ALSO 336 | .BR ktcheck (1), 337 | .BR lapply (1), 338 | .BR lcksum (1), 339 | .BR lcreate (1), 340 | .BR lfdiff (1), 341 | .BR lmerge (1), 342 | .BR lsort (1), 343 | .BR twhich (1), 344 | .BR applefile (5), 345 | .BR radmind (8). 346 | -------------------------------------------------------------------------------- /man/ktcheck.1: -------------------------------------------------------------------------------- 1 | .TH ktcheck "1" "_RADMIND_BUILD_DATE" "RSUG" "User Commands" 2 | .SH NAME 3 | .B ktcheck 4 | \- verify and download command file and transcripts 5 | .SH SYNOPSIS 6 | .B ktcheck 7 | .RB [ \-CIinrV ] 8 | [ 9 | .RB \-q\ |\ \-v 10 | ] [ 11 | .BI \-D\ path 12 | ] [ 13 | .BI \-e\ event 14 | ] [ 15 | .BI \-c\ checksum 16 | ] [ 17 | .BI \-K\ command-file 18 | ] [ 19 | .BI \-h\ host 20 | ] [ 21 | .BI \-p\ port 22 | ] [ 23 | .BI \-P\ ca-pem-directory 24 | ] [ 25 | .BI \-w\ auth-level 26 | ] [ 27 | .BI \-x\ ca-pem-file 28 | ] [ 29 | .BI \-y\ cert-pem-file 30 | ] [ 31 | .BI \-z\ private-key-file 32 | ] [ 33 | .BI \-Z\ compression-level 34 | ] 35 | .SH DESCRIPTION 36 | .B ktcheck 37 | verifies a client's command file with the radmind server 38 | .IR host . 39 | The command file is downloaded from 40 | .I host 41 | if it is missing or has the wrong size. With the -c option, checksums are 42 | also used to verify files. 43 | 44 | Reading the command file line-by-line, 45 | .B ktcheck 46 | verifies each command file and transcript listed, downloading it from 47 | .I host 48 | if it is missing or out of date. 49 | .B ktcheck 50 | ignors blank lines and comments ( lines starting with '#' ). 51 | Included command files are read are verified using the same method. 52 | 53 | Each special file listed in the command file is converted into a 54 | transcript line in special.T with information provided by 55 | .IR host . 56 | See 57 | .BR radmind (8) 58 | for details of the STAT command. 59 | 60 | If checksuming is turned on, the special transcript is verified using 61 | the checksum and file size. If either are wrong, the special transcript 62 | is updated. 63 | If checksuming is 64 | turned off, the special transcript is always updated. 65 | 66 | Files updated by 67 | .B ktcheck 68 | must be regular files and the user must have access to modify them. 69 | 70 | When run with the \-n option, 71 | .B ktcheck 72 | verifies but never downloads the command files or transcripts. A temporary 73 | special.T is created for verification and is removed on exit. 74 | .SH OPTIONS 75 | .TP 19 76 | .BI \-C 77 | clean 78 | .BR _RADMIND_DIR/client . 79 | .TP 19 80 | .BI \-c\ checksum 81 | enables checksuming. 82 | .TP 19 83 | .BI \-D\ path 84 | specifies the radmind working directory, by default 85 | .BR _RADMIND_PATH . 86 | .TP 19 87 | .BI \-e\ event 88 | the event type to report. This is limited to a single word, containing no 89 | white space. By default this is "ktcheck". 90 | .TP 19 91 | .BI \-I 92 | case-insensitive special.T, case-insensitive clean-up. 93 | .TP 19 94 | .BI \-i 95 | force output line buffering. 96 | .TP 19 97 | .BI \-h\ host 98 | specifies the radmind server, by default 99 | .BR _RADMIND_HOST . 100 | .TP 19 101 | .BI \-K\ command 102 | specifies a command file, by default 103 | .BR _RADMIND_COMMANDFILE . 104 | .TP 19 105 | .B \-n 106 | no files modified. 107 | .TP 19 108 | .BI \-p\ port 109 | specifies a port, by default 110 | .B 6222. 111 | .TP 19 112 | .BI \-P\ ca-pem-directory 113 | specifies a directory that contains certificates to be used when verifying the 114 | server. Certificates must be in PEM format and the directory must have been 115 | processed with the openssl c_rehash utility. 116 | .TP 19 117 | .B \-q 118 | suppress all messages. 119 | .TP 19 120 | .B \-r 121 | use random seed file $RANDFILE if that environment variable is set, 122 | $HOME/.rnd otherwise. See 123 | .BR RAND_load_file (3o). 124 | .TP 19 125 | .B \-V 126 | displays the version of 127 | .BR ktcheck , 128 | a list of supported checksumming algorithms in descending 129 | order of preference and then exits. 130 | .TP 19 131 | .B \-v 132 | displays communication with the radmind server. 133 | .TP 19 134 | .BI \-w\ auth-level 135 | TLS authorization level, by default _RADMIND_AUTHLEVEL. 136 | 0 = no TLS, 1 = server verification, 2 = server and client verification. 137 | .TP 19 138 | .BI \-x\ ca-pem-file 139 | Certificate authority's public certificate, by default _RADMIND_TLS_CA. 140 | The default is not used when -P is specified. 141 | .TP 19 142 | .BI \-y\ cert-pem-file 143 | Client's public certificate, by default _RADMIND_TLS_CERT. 144 | .TP 19 145 | .BI \-z\ private-key-file 146 | Client's private key, by default _RADMIND_TLS_CERT. 147 | .TP 19 148 | .BI \-Z\ compression-level 149 | Compress all outbound data. compression-level can be between 0 and 9: 150 | 1 gives best speed, 9 gives best compression, 0 gives no compression at 151 | all (the input data is simply copied a block at a time). 152 | .SH FILES 153 | .TP 19 154 | .B _RADMIND_COMMANDFILE 155 | name of the default command file. 156 | .TP 19 157 | .B special.T 158 | name of the special transcript. 159 | .SH EXIT STATUS 160 | The following exit values are returned: 161 | .TP 5 162 | 0 163 | No differences were found. 164 | .TP 5 165 | 1 166 | Differences were found. 167 | .TP 5 168 | >1 169 | An error occurred. 170 | .SH SEE ALSO 171 | .BR fsdiff (1), 172 | .BR lapply (1), 173 | .BR lcksum (1), 174 | .BR lcreate (1), 175 | .BR lfdiff (1), 176 | .BR lmerge (1), 177 | .BR lsort (1), 178 | .BR twhich (1), 179 | .BR radmind (8), 180 | .BR RAND_load_file (3o). 181 | -------------------------------------------------------------------------------- /man/lapply.1: -------------------------------------------------------------------------------- 1 | .TH lapply "1" "_RADMIND_BUILD_DATE" "RSUG" "User Commands" 2 | .SH NAME 3 | .B lapply 4 | \- modify file system to match apply-able-transcript 5 | .SH SYNOPSIS 6 | .B lapply 7 | .RB [ \-CFiInrV ] 8 | [ 9 | .RB \-%\ |\ \-q\ |\ \-v 10 | ] [ 11 | .BI \-c\ checksum 12 | ] [ 13 | .BI \-e\ event 14 | ] [ 15 | .BI \-h\ host 16 | ] [ 17 | .BI \-p\ port 18 | ] [ 19 | .BI \-P\ ca-pem-directory 20 | ] [ 21 | .BI \-u\ umask 22 | ] [ 23 | .BI \-w\ auth-level 24 | ] [ 25 | .BI \-x\ ca-pem-file 26 | ] [ 27 | .BI \-y\ cert-pem-file 28 | ] [ 29 | .BI \-z\ private-key-file 30 | ] [ 31 | .BI \-Z\ compression-level 32 | ] { 33 | .I apply-able-transcript 34 | } 35 | .SH DESCRIPTION 36 | lapply reads an apply-able transcript line-by-line, modifying the file 37 | system to match the transcript. Transcript lines are applied in order 38 | unless they are directories marked for deletion. In such cases, 39 | subsequent transcript lines are first applied until the file system object 40 | listed is outside of the directory. If another directory marked for 41 | deletion is encountered, the process is started recursively. 42 | .sp 43 | lapply downloads missing files indicated by a "+" from the radmind server 44 | .I host. 45 | .I file 46 | is applied to the system with the attributes as described in 47 | the transcript line. File system objects marked with a "-" are removed. 48 | Other transcript lines indicate that a file system 49 | object must be modified or created if missing. lapply is not able to create 50 | doors or sockets. 51 | .sp 52 | File system objects listed in the transcript and present in the 53 | file system as a different type are automatically removed. 54 | .sp 55 | By default, 56 | .B lapply 57 | will exit with an error if an object's full path is not present on the file 58 | system. When run with the -C option, 59 | .B lapply 60 | will attempt to create any intermediate directories that are missing. 61 | Intermediated directories inherit the owner, group and permissions of its 62 | parent directory. 63 | .sp 64 | The radmind tools are unaware of user defined file flags, some of which 65 | may prevent lapply from successfully completing. Using the -F option, 66 | .B lapply 67 | will remove all user defined flags. 68 | .sp 69 | If 70 | .I apply-able-transcript 71 | is not given, 72 | .B lapply 73 | will use the standard input for reading. 74 | .sp 75 | .B lapply 76 | is also capable of decoding 77 | .B applefiles 78 | stored on the server by 79 | .B lcreate(1), 80 | restoring the files' Mac OS HFS+ metadata to the client machine. (Mac OS X, 81 | HFS+-formatted drives only.) 82 | .SH OPTIONS 83 | .TP 19 84 | .BI \-% 85 | percentage done progress output. 86 | .TP 19 87 | .BI \-c\ checksum 88 | enables checksuming. 89 | .TP 19 90 | .BI \-C 91 | create missing intermediate directories. 92 | .TP 19 93 | .BI \-e\ event 94 | the event type to report. This is limited to a single word, containing no 95 | white space. By default this is "lapply". 96 | .TP 19 97 | .BI \-h\ host 98 | specifies the radmind server, by default 99 | .BR _RADMIND_HOST . 100 | .TP 19 101 | .BI \-i 102 | force output linebuffering. 103 | .TP 19 104 | .BI \-I 105 | be case insensitive when comparing paths. 106 | .TP 19 107 | .B \-F 108 | remove all user defined flags for a file if they exist. 109 | .TP 19 110 | .B \-n 111 | no network connection will be made, causing only file system removals and 112 | updates to be applied. auth-level is implicitly set to 0. 113 | .TP 19 114 | .BI \-p\ port 115 | specifies the port of the radmind server, by default 116 | .BR 6222 . 117 | .TP 19 118 | .BI \-P\ ca-pem-directory 119 | specifies a directory that contains certificates to be used when verifying the server. Certificates must be in PEM format and the directory must have been 120 | processed with the openssl c_rehash utility. 121 | .TP 19 122 | .B \-q 123 | suppress all messages. 124 | .TP 19 125 | .B \-r 126 | use random seed file $RANDFILE if that environment variable is set, 127 | $HOME/.rnd otherwise. See 128 | .BR RAND_load_file (3o). 129 | .TP 130 | .BI \-u\ umask 131 | specifies the umask for temporary files, by default 0077 132 | .TP 19 133 | .B \-V 134 | displays the version number of 135 | .B lapply 136 | and exits. 137 | .TP 19 138 | .B \-v 139 | displays communication with the radmind server. 140 | .TP 19 141 | .BI \-w\ auth-level 142 | TLS authorization level, by default _RADMIND_AUTHLEVEL. 143 | 0 = no TLS, 1 = server verification, 2 = server and client verification. 144 | .TP 19 145 | .BI \-x\ ca-pem-file 146 | Certificate authority's public certificate, by default _RADMIND_TLS_CA. 147 | The default is not used when -P is specified. 148 | .TP 19 149 | .BI \-y\ cert-pem-file 150 | Client's public certificate, by default _RADMIND_TLS_CERT. 151 | .TP 19 152 | .BI \-z\ private-key-file 153 | Client's private key, by default _RADMIND_TLS_CERT. 154 | .TP 19 155 | .BI \-Z\ compression-level 156 | Compress all outbound data. compression-level can be between 0 and 9: 157 | 1 gives best speed, 9 gives best compression, 0 gives no compression at 158 | all (the input data is simply copied a block at a time). 159 | .SH EXIT STATUS 160 | The following exit values are returned: 161 | .TP 5 162 | 0 163 | Transcript was applied. 164 | .TP 5 165 | 1 166 | An error occurred, system was modified. 167 | .TP 5 168 | 2 169 | An error occurred, system was not modified. 170 | .SH SEE ALSO 171 | .BR fsdiff (1), 172 | .BR ktcheck (1), 173 | .BR lcksum (1), 174 | .BR lcreate (1), 175 | .BR lfdiff (1), 176 | .BR lmerge (1), 177 | .BR lsort (1), 178 | .BR twhich (1), 179 | .BR applefile (5), 180 | .BR radmind (8), 181 | .BR chflags (2), 182 | .BR RAND_load_file (3o). 183 | -------------------------------------------------------------------------------- /man/lcksum.1: -------------------------------------------------------------------------------- 1 | .TH lcksum "1" "_RADMIND_BUILD_DATE" "RSUG" "User Commands" 2 | .SH NAME 3 | .B lcksum 4 | \- verifies a transcript's checksums and file sizes 5 | .SH SYNOPSIS 6 | .B lcksum 7 | .RB [ \-%AiIqV ] 8 | [ 9 | .BI \-D\ path 10 | ] [ 11 | .BI \-n 12 | [ 13 | .BI \-a 14 | ]] [ 15 | .BI \-P\ prefix 16 | ] 17 | .BI \-c\ checksum 18 | .I transcript 19 | .I ... 20 | .sp 21 | .SH DESCRIPTION 22 | .B lcksum 23 | verifies and updates the checksums and file sizes of the 24 | transcript 25 | .I transcript 26 | line-by-line. If more than one transcript is passed to 27 | .B lcksum, 28 | all transcripts will be verified and updated. 29 | .B lcksum 30 | compares the checksum and 31 | file size listed in 32 | .I transcript 33 | to that 34 | of the file in the file system. Files must be located in 35 | file directory associated with 36 | .IR transcript . 37 | With the \-n option 38 | .B lcksum 39 | verifies but does not modify 40 | .IR transcript . 41 | 42 | If there is a difference in either the checksum or file size, the 43 | transcript line is updated using the checksum, file size and 44 | modification time of the actual file. 45 | 46 | In update mode, 47 | .B lcksum 48 | may modify the file sizes and/or checksums in 49 | .IR transcript , 50 | so the user must have write access to 51 | .IR transcript . 52 | If an error occurs during an update of 53 | .IR transcript , 54 | lcksum removes the temporary copy of 55 | .IR transcript 56 | that it created and exits with a status of 2. 57 | 58 | .B lcksum 59 | also verifies that 60 | .I transcript 61 | is sorted in depth first order. 62 | 63 | With the \-P option, 64 | .B lcksum 65 | will only verify transcript lines with paths starting with 66 | .IR prefix . 67 | .sp 68 | .SH OPTIONS 69 | .TP 19 70 | .B \-% 71 | progress output. 72 | .TP 19 73 | .B \-a 74 | continue checking on error. Requires -n option. 75 | .TP 19 76 | .B \-A 77 | verify AppleSingle headers. 78 | .TP 19 79 | .BI \-c\ checksum 80 | enables checksuming. 81 | .TP 19 82 | .BI \-D\ path 83 | specifies the radmind working directory, by default _RADMIND_PATH 84 | .TP 19 85 | .B \-i 86 | force line buffering. 87 | .TP 19 88 | .BI \-I 89 | be case insensitive when compairing paths. 90 | .TP 19 91 | .B \-n 92 | verify but do not modify 93 | .IR transcript . 94 | .TP 19 95 | .BI \-P\ prefix 96 | only verify transcript lines that begin with 97 | .IR prefix . 98 | .TP 19 99 | .B \-q 100 | suppress all messages. 101 | .TP 19 102 | .B \-V 103 | displays the version of 104 | .BR lcksum 105 | and a list of supported checksumming algorithms in descending 106 | order of preference and then exits. 107 | .sp 108 | .SH EXIT STATUS 109 | The following exit values are returned: 110 | .TP 5 111 | 0 112 | Transcript was verified. 113 | .TP 5 114 | 1 115 | Differences were found. 116 | .TP 5 117 | >1 118 | An error occurred. 119 | .sp 120 | .SH SEE ALSO 121 | .BR fsdiff (1), 122 | .BR ktcheck (1), 123 | .BR lapply (1), 124 | .BR lcreate (1), 125 | .BR lfdiff (1), 126 | .BR lmerge (1), 127 | .BR lsort (1), 128 | .BR twhich (1), 129 | .BR radmind (8). 130 | -------------------------------------------------------------------------------- /man/lcreate.1: -------------------------------------------------------------------------------- 1 | .TH lcreate "1" "_RADMIND_BUILD_DATE" "RSUG" "User Commands" 2 | .SH NAME 3 | .B lcreate 4 | \- upload transcripts and their corresponding files 5 | .SH SYNOPSIS 6 | .B lcreate 7 | .RB [ \-FilnNrTV ] 8 | [ 9 | .RB \-%\ |\ \-q\ |\ \-v 10 | ] [ 11 | .BI \-c\ checksum 12 | ] [ 13 | .BI \-h\ host 14 | ] [ 15 | .BI \-p\ port 16 | ] [ 17 | .BI \-P\ ca-pem-directory 18 | ] [ 19 | .BI \-t\ stored-name 20 | ] [ 21 | .BI \-U\ user 22 | ] [ 23 | .BI \-w\ auth-level 24 | ] [ 25 | .BI \-x\ ca-pem-file 26 | ] [ 27 | .BI \-y\ cert-pem-file 28 | ] [ 29 | .BI \-z\ private-key-file 30 | ] [ 31 | .BI \-Z\ compression-level 32 | ] 33 | .I create-able-transcript 34 | .SH DESCRIPTION 35 | .B lcreate 36 | reads and uploads a transcript and all corresponding files to the 37 | radmind server. 38 | .sp 39 | .B lcreate 40 | verifies the size listed in the transcript with the actual size of the file 41 | and stops on any differences. 42 | If the -F option is given, 43 | .B lcreate 44 | will store the file on the server and give a warning. 45 | .sp 46 | If the -n option is given, no files or transcripts are uploaded. Instead, 47 | .B lcreate 48 | uses 49 | .BR access (2) 50 | to verify that all files in the transcript exist in the 51 | filesystem, are readable by the user and have the same size as listed in the 52 | transcript. If used with the -c option, rather than calling 53 | .BR access (2), 54 | checksums are caluclated to 55 | verify file contents and user access. 56 | .sp 57 | If the -N option is 58 | given, indicating the transcript specified for upload is negative, 59 | .B lcreate 60 | will upload all corresponding files as zero length. 61 | .sp 62 | If the -T option is 63 | given, 64 | .B lcreate 65 | will upload the transcript only. No corresponding files will be 66 | uploaded. The transcript's stored name is, by default, the last part ( 67 | after the slash ) of the given path, or as specified by the name given 68 | with the -t option. 69 | .B lcreate 70 | will print ( to the standard output ) the entire protocol exchange with the 71 | radmind server when the -v option is given. 72 | .sp 73 | By default, 74 | .B lcreate 75 | displays the percentage of bytes processed in a format that can be passed directly to iHook. 76 | .sp 77 | .B lcreate 78 | stores a Macintosh HFS+ file's data and corresponding metadata in a single 79 | .B applefile(5) 80 | on the server. With the -N option, applefiles are stored with a zero length 81 | resource fork, zero length data fork and a creator type of RDMD. 82 | Systems running Mac OS X on UFS-formatted drives do not need 83 | this special support. 84 | .SH OPTIONS 85 | .TP 19 86 | .BI \-% 87 | percentage done progress output. 88 | .TP 19 89 | .BI \-c\ checksum 90 | enables checksuming. 91 | .TP 19 92 | .BI \-F 93 | ignore file size differences. 94 | .TP 19 95 | .BI \-h\ hostname 96 | specifies the radmind server, by default 97 | .BR _RADMIND_HOST . 98 | .TP 19 99 | .BI \-i 100 | force output linebuffering. 101 | .TP 19 102 | .B \-l 103 | Turn on user authentication. Requires a TLS. 104 | .TP 19 105 | .B \-N 106 | uploads a 107 | .B negative 108 | transcript then uploads all corresponding files as zero length. 109 | .TP 19 110 | .B \-n 111 | Don't upload any files or transcripts. Verify all 112 | files in the transcript exist in the filesystem and have the size listed 113 | in the transcript. 114 | .TP 19 115 | .BI \-p\ port 116 | specifies a port, by default 117 | .BR 6222 . 118 | .TP 19 119 | .BI \-P\ ca-pem-directory 120 | specifies a directory that contains certificates to be used when verifying the server. Certificates must be in PEM format and the directory must have been 121 | processed with the openssl c_rehash utility. 122 | .TP 19 123 | .B \-q 124 | suppress all messages. 125 | .TP 19 126 | .B \-r 127 | use random seed file $RANDFILE if that environment variable is set, 128 | $HOME/.rnd otherwise. See 129 | .BR RAND_load_file (3o). 130 | .TP 19 131 | .B \-T 132 | uploads the transcript only, and 133 | .B not 134 | the corresponding files. 135 | .TP 19 136 | .BI \-t\ stored-name 137 | specifies the name under which the transcript will be stored when saved 138 | on the server. 139 | .TP 19 140 | .BI \-U\ user 141 | Specifes the user for user authentication. By default, the login name 142 | returned by 143 | .B getlogin() 144 | will be used. 145 | .TP 19 146 | .B \-V 147 | displays the version of 148 | .BR lcreate , 149 | a list of supported checksumming algorithms in descending 150 | order of preference and then exits. 151 | .TP 19 152 | .B \-v 153 | increase the verbosity. -v produces one line for each file stored on the 154 | server. -vv displays all communication with the radmind server. 155 | .TP 19 156 | .BI \-w\ auth-level 157 | TLS authorization level, by default _RADMIND_AUTHLEVEL. 158 | 0 = no TLS, 1 = server verification, 2 = server and client verification. 159 | .TP 19 160 | .BI \-x\ ca-pem-file 161 | Certificate authority's public certificate, by default _RADMIND_TLS_CA. 162 | The default is not used when -P is specified. 163 | .TP 19 164 | .BI \-y\ cert-pem-file 165 | Client's public certificate, by default _RADMIND_TLS_CERT. 166 | .TP 19 167 | .BI \-z\ private-key-file 168 | Client's private key, by default _RADMIND_TLS_CERT. 169 | .TP 19 170 | .BI \-Z\ compression-level 171 | Compress all outbound data. compression-level can be between 0 and 9: 172 | 1 gives best speed, 9 gives best compression, 0 gives no compression at 173 | all (the input data is simply copied a block at a time). 174 | .SH SEE ALSO 175 | .BR fsdiff (1), 176 | .BR ktcheck (1), 177 | .BR lapply (1), 178 | .BR lcksum (1), 179 | .BR lfdiff (1), 180 | .BR lmerge (1), 181 | .BR lsort (1), 182 | .BR twhich (1), 183 | .BR applefile (5), 184 | .BR radmind (8), 185 | .BR RAND_load_file (3o). 186 | -------------------------------------------------------------------------------- /man/lfdiff.1: -------------------------------------------------------------------------------- 1 | .TH lfdiff "1" "_RADMIND_BUILD_DATE" "RSUG" "User Commands" 2 | .SH NAME 3 | .B lfdiff 4 | \- compare local files with copies on radmind server 5 | .SH SYNOPSIS 6 | .B lfdiff 7 | [ 8 | .B \-IrvV 9 | ] [ 10 | .BI \-T\ transcript 11 | | 12 | .B \-S 13 | ] [ 14 | .BI \-h\ host 15 | ] [ 16 | .BI \-p\ port 17 | ] [ 18 | .BI \-P\ ca-pem-directory 19 | ] [ 20 | .BI \-u\ umask 21 | ] [ 22 | .BI \-w\ auth-level 23 | ] [ 24 | .BI \-x\ ca-pem-file 25 | ] [ 26 | .BI \-y\ cert-pem-file 27 | ] [ 28 | .BI \-z\ private-key-file 29 | ] [ 30 | .BI \-Z\ compression-level 31 | ] [ 32 | .I supported\ diff\ options 33 | ] [ 34 | .B \-X 35 | .I unsupported\ diff\ options 36 | ] 37 | .I file 38 | .SH DESCRIPTION 39 | .B lfdiff 40 | retrieves 41 | .IR file , 42 | given as an unencoded path, 43 | from the radmind server 44 | .I host 45 | and writes it to 46 | /tmp. 47 | .I file 48 | is then compared to the local copy of 49 | .I file 50 | using 51 | .BR diff (1). 52 | The server copy and the local copy of 53 | .I file 54 | are passed to 55 | .BR diff (1) 56 | as file1 57 | and file2 arguments respectively. 58 | .I file 59 | is removed from /tmp on exit. 60 | .B lfdiff 61 | supports all single letter 62 | .BR diff (1) 63 | options not duplicated in 64 | .BR lfdiff . 65 | All other 66 | .BR diff (1) 67 | options are given using the \-X option. 68 | .SH OPTIONS 69 | .TP 19 70 | .B \-I 71 | compare paths case-insensitively 72 | .TP 19 73 | .BI \-h\ host 74 | specifies the radmind server, by default 75 | .BR _RADMIND_HOST . 76 | .TP 19 77 | .BI \-p\ port 78 | specifies the port of the radmind server, by default 79 | .BR 6222 . 80 | .TP 19 81 | .BI \-P\ ca-pem-directory 82 | specifies a directory that contains certificates to be used when verifying the server. Certificates must be in PEM format and the directory must have been 83 | processed with the openssl c_rehash utility. 84 | .TP 19 85 | .B \-r 86 | use random seed file $RANDFILE if that environment variable is set, 87 | $HOME/.rnd otherwise. See 88 | .BR RAND_load_file (3o). 89 | .TP 19 90 | .B \-S 91 | .I file 92 | is a special file. 93 | .TP 19 94 | .BI \-T\ transcript 95 | transcript that 96 | .I file 97 | is listed in. 98 | .TP 99 | .BI \-u\ umask 100 | specifies the umask for temporary files, by default 0077 101 | .TP 19 102 | .B \-V 103 | displays the version of 104 | .B lfdiff 105 | and exits. 106 | .TP 19 107 | .BI \-v 108 | display communication with the radmind server. 109 | .TP 19 110 | .BI \-X\ unsupported\ diff\ options 111 | passes options directly to 112 | .BR diff (1). 113 | .TP 19 114 | .BI \-w\ auth-level 115 | TLS authorization level, by default _RADMIND_AUTHLEVEL. 116 | 0 = no TLS, 1 = server verification, 2 = server and client verification. 117 | .TP 19 118 | .BI \-x\ ca-pem-file 119 | Certificate authority's public certificate, by default _RADMIND_TLS_CA. 120 | .TP 19 121 | .BI \-y\ cert-pem-file 122 | Client's public certificate, by default _RADMIND_TLS_CERT. 123 | The default is not used when -P is specified. 124 | .TP 19 125 | .BI \-z\ private-key-file 126 | Client's private key, by default _RADMIND_TLS_CERT. 127 | .TP 19 128 | .BI \-Z\ compression-level 129 | Compress all outbound data. compression-level can be between 0 and 9: 130 | 1 gives best speed, 9 gives best compression, 0 gives no compression at 131 | all (the input data is simply copied a block at a time). 132 | .SH EXIT STATUS 133 | The following exit values are returned: 134 | .TP 5 135 | 0 136 | No differences were found. 137 | .TP 5 138 | 1 139 | Differences were found. 140 | .TP 5 141 | >1 142 | An error occurred. 143 | .SH SEE ALSO 144 | .BR diff (1), 145 | .BR fsdiff (1), 146 | .BR ktcheck (1), 147 | .BR lapply (1), 148 | .BR lcksum (1), 149 | .BR lcreate (1), 150 | .BR lmerge (1), 151 | .BR lsort (1), 152 | .BR twhich (1), 153 | .BR radmind (8), 154 | .BR RAND_load_file (3o). 155 | -------------------------------------------------------------------------------- /man/lmerge.1: -------------------------------------------------------------------------------- 1 | .TH lmerge "1" "_RADMIND_BUILD_DATE" "RSUG" "User Commands" 2 | .SH NAME 3 | .B lmerge 4 | \- lmerge combines multiple transcripts into one. 5 | .SH SYNOPSIS 6 | .B lmerge 7 | .RB [ \-CIiVvT ] 8 | [ 9 | .BI \-D\ path 10 | ] [ 11 | .BI \-u\ umask 12 | ] 13 | .IR transcript ... 14 | .I dest 15 | .br 16 | .B lmerge 17 | .B \-f 18 | .RB [ \-IiVv ] 19 | [ 20 | .BI \-D\ path 21 | ] [ 22 | .BI \-u\ umask 23 | ] 24 | .I transcript1 transcript2 25 | .br 26 | .B lmerge 27 | .B \-n 28 | .RB [ \-IiVvT ] 29 | [ 30 | .BI \-D\ path 31 | ] [ 32 | .BI \-u\ umask 33 | ] 34 | .I transcript1 transcript2 dest 35 | .br 36 | .sp 37 | .SH DESCRIPTION 38 | .B lmerge 39 | walks through each transcript in precedence order ( highest precedence 40 | transcript listed first ) to create the apply-able transcript 41 | .IR dest . 42 | If multiple transcripts list the same file system object, the transcript 43 | line from the highest precedence transcript is written to 44 | .IR dest . 45 | 46 | Blank lines and comments ( lines starting with # ) are not written to 47 | .IR dest . 48 | 49 | With the \-f option 50 | .B lmerge 51 | does not create a new transcript and merges the first transcript into the 52 | second transcript. The second transcript must be writable by the user. 53 | Only two transcripts are allowed. 54 | 55 | If the highest precedence listing of a file system object is preceded with a 56 | \'-', the transcript line will not be written to 57 | .IR dest . 58 | 59 | Files listed in 60 | .I dest 61 | are linked from their original location to a file directory created by 62 | .BR lmerge . 63 | This directory is relative to the location of 64 | .IR dest . 65 | Since files are linked, all transcripts ( including 66 | .I dest 67 | ) and files must be located on the same volume. 68 | 69 | The \-C options runs 70 | .B lmerge 71 | in copy mode. Files listed in 72 | .I dest 73 | are copied from their original locations and are not linked. 74 | 75 | Using the \-f option, 76 | .B lmerge 77 | links all files from the lowest precedence 78 | transcript. If the transcript line for a file is preceded with a "-" 79 | it is also removed from the file directory associated with the lowest precedence 80 | transcript. 81 | 82 | The \-n option indicates that the highest precedence transcript has no 83 | associated file directory. All files listed in the highest precedence 84 | transcript must be in the file directory associated with the lowest precedence 85 | transcript. A transcript line in the highest precedence transcript written to 86 | .IR dest , 87 | but files are linked from the lowest precedence transcript. Only two 88 | transcripts can be merged with the \-n option. 89 | .SH OPTIONS 90 | .TP 19 91 | .B \-C 92 | enable copy mode. 93 | .TP 19 94 | .B \-f 95 | merge 96 | .B transcript1 97 | into 98 | .IR transcript2 . 99 | .TP 19 100 | .BI \-D\ path 101 | specifies the radmind working directory, by default _RADMIND_PATH 102 | .TP 19 103 | .BI \-I 104 | path comparisons are case-insensitive. 105 | .TP 19 106 | .B \-n 107 | merge two transcripts linking all files from the lowest precedence 108 | transcript. 109 | .TP 19 110 | .B \-T 111 | merge transcripts only. Do not perform file system linking. 112 | May not be used with the \-f option. 113 | .TP 19 114 | .BI \-u\ umask 115 | use 116 | .I umask 117 | as the file mode creation mask, default is users umask. 118 | .TP 19 119 | .B \-V 120 | displays the version of 121 | .B lmerge 122 | and exits. 123 | .TP 19 124 | .B \-v 125 | displays merge information to the standard output. 126 | .sp 127 | .SH EXIT STATUS 128 | The following exit values are returned: 129 | .TP 5 130 | 0 131 | Merge successful. 132 | .TP 5 133 | >1 134 | An error occurred. 135 | .sp 136 | .SH SEE ALSO 137 | .BR fsdiff (1), 138 | .BR ktcheck (1), 139 | .BR lapply (1), 140 | .BR lcksum (1), 141 | .BR lcreate (1), 142 | .BR lfdiff (1), 143 | .BR lsort (1), 144 | .BR twhich (1), 145 | .BR radmind (8). 146 | -------------------------------------------------------------------------------- /man/lsort.1: -------------------------------------------------------------------------------- 1 | .TH lsort "1" "_RADMIND_BUILD_DATE" "RSUG" "User Commands" 2 | .SH NAME 3 | .B lsort 4 | \- sort transcripts 5 | .SH SYNOPSIS 6 | .B lsort 7 | [ 8 | .RI \-IV 9 | ] [ 10 | .BI \-o\ file 11 | ] [ 12 | .I transcript ... 13 | ] 14 | .SH DESCRIPTION 15 | .B lsort 16 | sorts each 17 | .I transcript 18 | together and prints the results to the standard output. 19 | If 20 | .I transcript 21 | is not given, 22 | .B lsort 23 | will use the standard input for reading. 24 | .SH OPTIONS 25 | .TP 19 26 | .BI \-I 27 | be case insensitive when sorting transcripts. 28 | .TP 19 29 | .BI \-o\ file 30 | specifies an output file, default is the standard output. 31 | .TP 19 32 | .B \-V 33 | displays the version number of 34 | .BR lsort 35 | and exits. 36 | .SH EXIT STATUS 37 | The following exit values are returned: 38 | .TP 5 39 | 0 40 | No errors. 41 | .TP 5 42 | >0 43 | An error occurred. 44 | .SH SEE ALSO 45 | .BR fsdiff (1), 46 | .BR ktcheck (1), 47 | .BR lapply (1), 48 | .BR lcksum (1), 49 | .BR lcreate (1), 50 | .BR lfdiff (1), 51 | .BR lmerge (1), 52 | .BR lsort (1), 53 | .BR radmind (8). 54 | -------------------------------------------------------------------------------- /man/rash.1: -------------------------------------------------------------------------------- 1 | .TH rash "1" "_RADMIND_BUILD_DATE" "RSUG" "User Commands" 2 | .SH NAME 3 | .B rash 4 | \- Radmind Assistant 5 | .SH SYNOPSIS 6 | .B ra.sh 7 | [ 8 | .B -cIltV 9 | ] [ 10 | .B -% 11 | | 12 | .B -q 13 | ] [ 14 | .BR \-C\ "generate" 15 | | 16 | .BI \-C\ checksum 17 | ] [ 18 | .B \-D 19 | .I workingdir 20 | ] [ 21 | .B \-h 22 | .I server 23 | ] [ 24 | .B \-p 25 | .I port 26 | ] [ 27 | .B \-r 28 | .I path 29 | ] [ 30 | .B \-U 31 | .I user 32 | ] [ 33 | .B \-w 34 | .I authlevel 35 | ] { 36 | .B trip 37 | | 38 | .B update 39 | | 40 | .B create 41 | | 42 | .B auto 43 | | 44 | .B force 45 | | 46 | .B checkout 47 | | 48 | .B checkin 49 | } 50 | .sp 51 | .SH DESCRIPTION 52 | .B rash 53 | is a command line application for running the Radmind 54 | tool set. It can be used to run the entire radmind process including 55 | updating a client, running a tripwire and creating loadsets. On 56 | machines with multiple administrators, 57 | .B rash 58 | can be used to limit 59 | conflicts from multiple administrators simultaneously using the tool. 60 | 61 | .B rash 62 | is run with a required option telling it what process to run: 63 | update, auto, force, create, trip, checkout or checkin. 64 | 65 | A machine can be updated by using either the update, auto or force 66 | option. update will prompt the user at each step in the process. auto 67 | will update the machine without any input, looping when possible to 68 | handle temporary problems such as networking issues or a busy server. 69 | auto is suitable to be run as an automated process. force updates 70 | a machine without looping or prompting for input and is handy for quick, 71 | manual updates. 72 | 73 | create is used to store a loadset on the radmind server in an 74 | interactive fashion. Before creating a transcript, 75 | .B rash 76 | first checks to 77 | see if the command file and transcripts are correct and prompts the user 78 | to update them if needed. The user can also edit the transcript before 79 | it is stored on the server. 80 | 81 | trip is used to run a tripwire on the system. If the command file and 82 | transcripts are correct, a full tripwire is run with checksums. Any 83 | differences are printed to the screen in a format suitable for e-mailed 84 | machine reporting. 85 | 86 | checkout is used to prevent other users from concurrently running 87 | .BR rash . 88 | It is helpful when an administrator is installing new software or 89 | configuring a client and does not want their work removed. Only the 90 | user who checked out a machine can run 91 | .B rash 92 | unless a new checkout is 93 | forced from an interactive 94 | .B rash 95 | session. An e-mail is sent to the 96 | previous users when a checkout is overridden. As trip does not modify 97 | the system, it can be run at any time, regardless of who has checked out 98 | the machine. checkin is used to release a machine. Only the user who 99 | checked out a machine may check it back in. 100 | 101 | checkin and checkout both use $USER to determine who is performing 102 | the command. $USER can be overridden using the -U option. 103 | 104 | The -c option can be used to turn on checksums for fsdiff. The only 105 | supported checksum is SHA1. 106 | 107 | .B rash 108 | supports running arbitrary scripts before and after lapply. 109 | Preapply scripts located in PREAPPLY are run before lapply, and 110 | postapply scripts located in POSTAPPLY are run after. The first 111 | argument passed to each script is the full path to apply-able 112 | transcript. 113 | .SH OPTIONS 114 | .TP 19 115 | .B \-% 116 | Tell 117 | .BR fsdiff (1) 118 | , 119 | .BR lapply (1) 120 | , and 121 | .BR lcreate (1) 122 | to use percentage done progress output. 123 | .TP 19 124 | .B \-c 125 | use sha1 checksums. 126 | .TP 19 127 | .BR \-C\ "generate" 128 | Print a sha1 checksum of the difference transcript of applied changes. For use with 129 | .IR auto , 130 | .IR force 131 | or 132 | .IR update . 133 | .TP 19 134 | .BI \-C\ checksum 135 | In 136 | .I auto 137 | mode, exit with an error if the checksum of the difference transcript to be applied does not match 138 | .IR checksum . 139 | In 140 | .I update 141 | or 142 | .I force 143 | mode, warn if the two do not match. 144 | .TP 19 145 | .BI \-D\ workingdir 146 | change to 147 | .I workingdir 148 | before running. Default is "/". 149 | .TP 19 150 | .BI \-h\ hostname 151 | specifies the radmind server, by default 152 | .BR _RADMIND_HOST . 153 | .TP 19 154 | .B \-I 155 | Tell 156 | .BR fsdiff (1) 157 | , 158 | .BR ktcheck (1) 159 | , and 160 | .BR lapply (1) 161 | to use case-insensitive matching. 162 | .TP 19 163 | .B \-l 164 | Prompt for remote user name. The -U option disables this prompt. 165 | .TP 19 166 | .BI \-p\ port 167 | Specifies the port to connect to the server on, by default 6222. 168 | .TP 19 169 | .B \-q 170 | Tell 171 | .BR lapply (1) 172 | and 173 | .BR lcreate (1) 174 | to operate quietly. 175 | .TP 19 176 | .BI \-r\ path 177 | specifies root path from which fsdiff will start its scan of the 178 | filesystem 179 | .TP 19 180 | .B \-t 181 | use tempfiles 182 | .TP 19 183 | .BI \-U\ user 184 | specifies the user. By default, $USER 185 | will be used. 186 | .TP 19 187 | .B \-V 188 | displays the version of 189 | .B rash 190 | and exits. 191 | .TP 19 192 | .BI \-w\ auth-level 193 | TLS authorization level, by default _RADMIND_AUTHLEVEL. 194 | 0 = no TLS, 1 = server verification, 2 = server and client verification. 195 | .SH EXIT STATUS 196 | The following exit values are returned: 197 | .TP 5 198 | 0 199 | successful. 200 | .TP 5 201 | >1 202 | An error occurred. 203 | .sp 204 | .SH SEE ALSO 205 | .BR fsdiff (1), 206 | .BR ktcheck (1), 207 | .BR lapply (1), 208 | .BR lcksum (1), 209 | .BR lcreate (1), 210 | .BR lfdiff (1), 211 | .BR lmerge (1), 212 | .BR lsort (1), 213 | .BR twhich (1), 214 | .BR radmind (8). 215 | -------------------------------------------------------------------------------- /man/repo.1: -------------------------------------------------------------------------------- 1 | .TH repo "1" "_RADMIND_BUILD_DATE" "RSUG" "User Commands" 2 | .SH NAME 3 | .B repo 4 | \- report events to a radmind server 5 | .SH SYNOPSIS 6 | .B repo 7 | .BI \-e\ event 8 | [ 9 | .RI \-Vv 10 | ] [ 11 | .BI \-h\ host 12 | ] [ 13 | .BI \-p\ port 14 | ] [ 15 | .BI \-w\ auth-level 16 | ] [ 17 | .BI \-x\ ca-pem-file 18 | ] [ 19 | .BI \-y\ cert-pem-file 20 | ] [ 21 | .BI \-z\ private-key-file 22 | ] [ 23 | .BI \-Z\ compression-level 24 | ] [ 25 | .I message ... 26 | ] 27 | .SH DESCRIPTION 28 | .B repo 29 | reports status messages to the radmind server. The administrator defines 30 | the 31 | .I event 32 | type with the -e option. The 33 | .I message 34 | is read from the command line or from standard input. The 35 | .I event 36 | and the 37 | .I message 38 | are logged by the server if 39 | .B repo 40 | succeeds. 41 | .SH OPTIONS 42 | .TP 19 43 | .BI \-e\ event 44 | the event type to report. This is limited to a single word, containing no 45 | white space. 46 | .TP 19 47 | .BI \-h\ host 48 | specifies the radmind server, by default 49 | .BR _RADMIND_HOST . 50 | .TP 19 51 | .BI \-p\ port 52 | specifies a port, by default 53 | .B 6222 . 54 | .TP 19 55 | .BI \-P\ ca-pem-directory 56 | specifies a directory that contains certificates to be used when verifying the server. Certificates must be in PEM format and the directory must have been 57 | processed with the openssl c_rehash utility. 58 | .TP 19 59 | .B \-V 60 | displays the version of 61 | .BR repo , 62 | and exits. 63 | .TP 19 64 | .B \-v 65 | displays communication with the radmind server. 66 | .TP 19 67 | .BI \-w\ auth-level 68 | TLS authorization level, by default _RADMIND_AUTHLEVEL. 69 | 0 = no TLS, 1 = server verification, 2 = server and client verification. 70 | .TP 19 71 | .BI \-x\ ca-pem-file 72 | Certificate authority's public certificate, by default _RADMIND_TLS_CA. 73 | The default is not used when -P is specified. 74 | .TP 19 75 | .BI \-y\ cert-pem-file 76 | Client's public certificate, by default _RADMIND_TLS_CERT. 77 | .TP 19 78 | .BI \-z\ private-key-file 79 | Client's private key, by default _RADMIND_TLS_CERT. 80 | .TP 19 81 | .BI \-Z\ compression-level 82 | Compress all outbound data. compression-level can be between 0 and 9: 83 | 1 gives best speed, 9 gives best compression, 0 gives no compression at 84 | all (the input data is simply copied a block at a time). 85 | .SH EXIT STATUS 86 | The following exit values are returned: 87 | .TP 5 88 | 0 89 | No errors. 90 | .TP 5 91 | >0 92 | An error occurred. 93 | .SH SEE ALSO 94 | .BR radmind (8). 95 | -------------------------------------------------------------------------------- /man/twhich.1: -------------------------------------------------------------------------------- 1 | .TH twhich "1" "_RADMIND_BUILD_DATE" "RSUG" "User Commands" 2 | .SH NAME 3 | .B twhich 4 | \- locates a file listing in transcripts 5 | .SH SYNOPSIS 6 | .B twhich 7 | [ 8 | .RI \-aIrV 9 | ] [ 10 | .BI \-K\ command 11 | ] 12 | .I file 13 | .br 14 | .B twhich 15 | .B \-s 16 | .BI \-K\ command 17 | [ 18 | .RI \-aIV 19 | ] 20 | .I file 21 | .sp 22 | .SH DESCRIPTION 23 | .B twhich 24 | searches each transcript listed in the command file ( the default name is 25 | .B command.K ) 26 | for 27 | .IR file . 28 | Transcripts are searched in precedence order. 29 | The first 30 | transcript listed in the command file has the lowest precedence, the 31 | next higher, and the last has the highest. If any special files are 32 | listed, the 33 | .B special.T 34 | transcript will have the absolute highest precedence. 35 | .I file 36 | must be the full decoded path (See 37 | .BR fsdiff (1)), 38 | as listed in the transcript. 39 | 40 | If 41 | .I file 42 | is found, 43 | .B twhich 44 | prints a message to the standard output indicating the transcript, line 45 | number and matching line, and then exits. With the -a option, 46 | .B twhich 47 | will continue to search all transcripts listed in the command file for 48 | .IR file . 49 | With the -r option, 50 | .B twhich 51 | will search for each path component, progressively building to 52 | .IR file , 53 | behaving as above when matches are found. If a path element in 54 | .I file 55 | is missing, twhich will print "not found" and continue looking for 56 | the next element. 57 | 58 | The -s option is used to run 59 | .B twhich 60 | on a radmind server. When run on a server, the command file to search 61 | must be given with the -K option. All listed transcripts 62 | must be in the respective radmind server transcript directory. 63 | 64 | .sp 65 | .SH OPTIONS 66 | .TP 19 67 | .B \-a 68 | list all transcripts that contain 69 | .IR file . 70 | .TP 19 71 | .BI \-I 72 | be case insensitive when comparing paths. 73 | .TP 19 74 | .BI \-K\ command 75 | specifies a command 76 | file, by default 77 | .BR _RADMIND_COMMANDFILE 78 | .TP 19 79 | .B \-s 80 | indicates that 81 | .B twhich 82 | is running on a radmind server. 83 | .TP 19 84 | .B \-r 85 | searches for each path element in 86 | .IR file . 87 | .TP 19 88 | .B \-V 89 | displays the version number of 90 | .BR twhich 91 | and exits. 92 | .sp 93 | .SH FILES 94 | .TP 19 95 | .B _RADMIND_COMMANDFILE 96 | name of the default command file. 97 | .TP 19 98 | .B special.T 99 | name of the special transcript. 100 | .SH EXIT STATUS 101 | The following exit values are returned: 102 | .TP 5 103 | 0 104 | File was found. 105 | .TP 5 106 | 1 107 | File was not found. 108 | .TP 5 109 | >1 110 | An error occurred. 111 | .sp 112 | .SH SEE ALSO 113 | .BR fsdiff (1), 114 | .BR ktcheck (1), 115 | .BR lapply (1), 116 | .BR lcksum (1), 117 | .BR lcreate (1), 118 | .BR lfdiff (1), 119 | .BR lmerge (1), 120 | .BR lsort (1), 121 | .BR radmind (8). 122 | -------------------------------------------------------------------------------- /mkdirs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "mkdirs.h" 14 | 15 | /* 16 | * The right most element of the path is assumed to be a file. 17 | */ 18 | int 19 | mkdirs( char *path ) 20 | { 21 | char *p, *q = NULL; 22 | int saved_errno; 23 | 24 | saved_errno = errno; 25 | 26 | /* try making longest path first, working backward */ 27 | for (;;) { 28 | if (( p = strrchr( path, '/' )) == NULL ) { 29 | errno = EINVAL; 30 | return( -1 ); 31 | } 32 | *p = '\0'; 33 | if ( q != NULL ) { 34 | *q = '/'; 35 | } 36 | 37 | if ( mkdir( path, 0777 ) == 0 ) { 38 | break; 39 | } 40 | if ( errno == EEXIST ) { 41 | break; 42 | } else if ( errno != ENOENT ) { 43 | return( -1 ); 44 | } 45 | q = p; 46 | } 47 | 48 | *p = '/'; 49 | 50 | if ( q != NULL ) { 51 | p++; 52 | for ( p = strchr( p, '/' ); p != NULL; p = strchr( p, '/' )) { 53 | *p = '\0'; 54 | if ( mkdir( path, 0777 ) < 0 ) { 55 | if ( errno != EEXIST ) { 56 | return( -1 ); 57 | } 58 | } 59 | *p++ = '/'; 60 | } 61 | } 62 | 63 | errno = saved_errno; 64 | 65 | return( 0 ); 66 | } 67 | -------------------------------------------------------------------------------- /mkdirs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | int mkdirs( char *path ); 7 | -------------------------------------------------------------------------------- /mkprefix.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "mkprefix.h" 17 | 18 | int extern quiet; 19 | int extern showprogress; 20 | 21 | /* mkprefix attempts to create intermediate directories of path. 22 | * Intermediate directories are created with the permission of the 23 | * mode and UID of the last pre-existing parent directory. 24 | */ 25 | 26 | int 27 | mkprefix( char *path ) 28 | { 29 | char *p, parent_path[ MAXPATHLEN * 2 ]; 30 | int saved_errno, parent_stats = 0; 31 | uid_t e_uid; 32 | struct stat st, parent_st; 33 | mode_t mode = 0777; 34 | 35 | e_uid = geteuid(); 36 | 37 | /* Move past any leading /'s */ 38 | for ( p = path; *p == '/'; p++ ) 39 | ; 40 | 41 | /* Attempt to create each intermediate directory of path */ 42 | for ( p = strchr( p, '/' ); p != NULL; p = strchr( p, '/' )) { 43 | *p = '\0'; 44 | if ( mkdir( path, mode ) < 0 ) { 45 | /* Only error if path exists and it's not a directory */ 46 | saved_errno = errno; 47 | if ( stat( path, &st ) != 0 ) { 48 | errno = saved_errno; 49 | return( -1 ); 50 | } 51 | if ( !S_ISDIR( st.st_mode )) { 52 | errno = EEXIST; 53 | return( -1 ); 54 | } 55 | errno = 0; 56 | *p++ = '/'; 57 | continue; 58 | } 59 | 60 | /* Get stats from parent of first missing directory */ 61 | if ( !parent_stats ) { 62 | if ( snprintf( parent_path, MAXPATHLEN, "%s/..", path) 63 | > MAXPATHLEN ) { 64 | fprintf( stderr, "%s/..: path too long\n", path ); 65 | *p++ = '/'; 66 | return( -1 ); 67 | } 68 | if ( stat( parent_path, &parent_st ) != 0 ) { 69 | return( -1 ); 70 | } 71 | parent_stats = 1; 72 | } 73 | 74 | /* Set mode to that of last preexisting parent */ 75 | if ( mode != parent_st.st_mode ) { 76 | if ( chmod( path, parent_st.st_mode ) != 0 ) { 77 | return( -1 ); 78 | } 79 | } 80 | 81 | /* Set uid to that of last preexisting parent */ 82 | if ( e_uid != parent_st.st_uid ) { 83 | if ( chown( path, parent_st.st_uid, parent_st.st_gid ) != 0 ) { 84 | return( -1 ); 85 | } 86 | } 87 | 88 | if ( !quiet && !showprogress ) { 89 | printf( "%s: created missing prefix\n", path ); 90 | } 91 | 92 | *p++ = '/'; 93 | } 94 | return( 0 ); 95 | } 96 | -------------------------------------------------------------------------------- /mkprefix.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | int mkprefix( char *path ); 7 | -------------------------------------------------------------------------------- /openssl_compat.c: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenSSL Compatibility Shims for pre-1.1.0 3 | * 4 | */ 5 | 6 | #include "openssl_compat.h" 7 | #if OPENSSL_VERSION_NUMBER < 0x10100000L 8 | 9 | static void *OPENSSL_zalloc(size_t num) 10 | { 11 | void *ret = OPENSSL_malloc(num); 12 | 13 | if (ret != NULL) 14 | memset(ret, 0, num); 15 | return ret; 16 | } 17 | 18 | EVP_MD_CTX *EVP_MD_CTX_new(void) 19 | { 20 | return OPENSSL_zalloc(sizeof(EVP_MD_CTX)); 21 | } 22 | 23 | void EVP_MD_CTX_free(EVP_MD_CTX *ctx) 24 | { 25 | EVP_MD_CTX_cleanup(ctx); 26 | OPENSSL_free(ctx); 27 | } 28 | 29 | #endif // OLD OPENSSL <1.1.0 30 | -------------------------------------------------------------------------------- /openssl_compat.h: -------------------------------------------------------------------------------- 1 | /* 2 | * OpenSSL Compatibility Shims for pre-1.1.0 3 | * 4 | */ 5 | 6 | #include 7 | 8 | #if OPENSSL_VERSION_NUMBER < 0x10100000L 9 | #include 10 | #include 11 | 12 | EVP_MD_CTX *EVP_MD_CTX_new(void); 13 | void EVP_MD_CTX_free(EVP_MD_CTX *ctx); 14 | 15 | #endif // OLD OPENSSL <1.1.0 16 | -------------------------------------------------------------------------------- /pathcmp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | #include "config.h" 7 | 8 | #ifdef __APPLE__ 9 | #define USE_ASCII 1 10 | #endif /* __APPLE__ */ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "pathcmp.h" 18 | #include "code.h" 19 | 20 | int 21 | pathcasecmp( const char *p1, const char *p2, 22 | int case_sensitive ) 23 | { 24 | int rc; 25 | 26 | do { 27 | if ( case_sensitive ) { 28 | rc = ( (unsigned char)*p1 - (unsigned char)*p2 ); 29 | } else { 30 | rc = ( tolower( *p1 ) - tolower( *p2 )); 31 | } 32 | 33 | if ( rc != 0 ) { 34 | if (( *p2 != '\0' ) && ( *p1 == '/' )) { 35 | return( -1 ); 36 | } else if (( *p1 != '\0' ) && ( *p2 == '/' )) { 37 | return( 1 ); 38 | } else { 39 | return( rc ); 40 | } 41 | } 42 | p2++; 43 | } while ( *p1++ != '\0' ); 44 | 45 | return( 0 ); 46 | } 47 | 48 | /* Just like strcmp(), but pays attention to the meaning of '/'. */ 49 | int 50 | pathcmp( const char *p1, const char *p2 ) 51 | { 52 | return( pathcasecmp( p1, p2, 1 )); 53 | } 54 | 55 | int 56 | ischildcase( const char *child, const char *parent, int 57 | case_sensitive ) 58 | { 59 | int rc; 60 | size_t parentlen; 61 | 62 | 63 | if ( parent == NULL ) { 64 | return( 1 ); 65 | } 66 | 67 | parentlen = strlen( parent ); 68 | 69 | if ( parentlen > strlen( child )) { 70 | return( 0 ); 71 | } 72 | if (( 1 == parentlen ) && ( '/' == *parent )) { 73 | return( '/' == *child ); 74 | } 75 | 76 | if ( case_sensitive ) { 77 | rc = strncmp( parent, child, parentlen ); 78 | } else { 79 | rc = strncasecmp( parent, child, parentlen ); 80 | } 81 | if (( rc == 0 ) && (( '/' == child[ parentlen ] ) || 82 | ( '\0' == child[ parentlen ] ))) { 83 | return( 1 ); 84 | } 85 | return( 0 ); 86 | } 87 | 88 | int 89 | ischild( const char *child, const char *parent ) 90 | { 91 | return( ischildcase( child, parent, 1 )); 92 | } 93 | -------------------------------------------------------------------------------- /pathcmp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | int pathcasecmp( const char *, const char *, 7 | int case_sensitive ); 8 | int pathcmp( const char *, const char * ); 9 | int ischildcase( const char *, const char *, 10 | int case_sensitive ); 11 | int ischild( const char *, const char * ); 12 | -------------------------------------------------------------------------------- /progress.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "argcargv.h" 11 | #include "code.h" 12 | #include "largefile.h" 13 | #include "progress.h" 14 | 15 | int progress = -1; 16 | int showprogress = 0; 17 | off_t lsize = 0, total = 0; 18 | 19 | void 20 | linecheck( char *line, int ac, int linenum ) 21 | { 22 | if ( ac < 8 ) { 23 | if ( line[ strlen( line ) - 1 ] == '\n' ) { 24 | line[ strlen( line ) - 1 ] = '\0'; 25 | } 26 | fprintf( stderr, "%s: line %d: invalid transcript line\n", 27 | line, linenum ); 28 | exit( 2 ); 29 | } 30 | } 31 | 32 | off_t 33 | loadsetsize( FILE *tran ) 34 | { 35 | char tline[ LINE_MAX ], line[ LINE_MAX ]; 36 | char **targv; 37 | int tac, linenum = 0; 38 | off_t size = 0; 39 | 40 | while ( fgets( tline, LINE_MAX, tran ) != NULL ) { 41 | linenum++; 42 | strcpy( line, tline ); 43 | if (( tac = argcargv( tline, &targv )) == 0 ) { 44 | continue; 45 | } 46 | 47 | switch ( *targv[ 0 ] ) { 48 | case 'a': 49 | case 'f': 50 | break; 51 | 52 | default: 53 | continue; 54 | } 55 | 56 | linecheck( line, tac, linenum ); 57 | size += strtoofft( targv[ 6 ], NULL, 10 ); 58 | } 59 | 60 | rewind( tran ); 61 | 62 | return( size ); 63 | } 64 | 65 | off_t 66 | applyloadsetsize( FILE *tran ) 67 | { 68 | char tline[ LINE_MAX ], line[ LINE_MAX ]; 69 | char **targv; 70 | int tac, linenum = 0; 71 | off_t size = 0; 72 | 73 | while ( fgets( tline, LINE_MAX, tran ) != NULL ) { 74 | linenum++; 75 | strcpy( line, tline ); 76 | /* skip empty lines and transcript marker lines */ 77 | if (( tac = argcargv( tline, &targv )) <= 1 ) { 78 | continue; 79 | } 80 | 81 | switch ( *targv[ 0 ] ) { 82 | case '+': 83 | switch ( *targv[ 1 ] ) { 84 | case 'a': 85 | case 'f': 86 | linecheck( line, tac, linenum ); 87 | size += strtoofft( targv[ 7 ], NULL, 10 ); 88 | 89 | default: 90 | break; 91 | } 92 | 93 | default: 94 | break; 95 | } 96 | 97 | size += PROGRESSUNIT; 98 | } 99 | 100 | rewind( tran ); 101 | 102 | return( size ); 103 | } 104 | 105 | off_t 106 | lcksum_loadsetsize( FILE *tran, char *prefix ) 107 | { 108 | char tline[ LINE_MAX ], line[ LINE_MAX ]; 109 | char *d_path = NULL; 110 | char **targv; 111 | int tac, linenum = 0; 112 | off_t size = 0; 113 | 114 | while ( fgets( tline, LINE_MAX, tran ) != NULL ) { 115 | linenum++; 116 | strcpy( line, tline ); 117 | if (( tac = argcargv( tline, &targv )) <= 1 ) { 118 | continue; 119 | } 120 | 121 | if ( prefix != NULL ) { 122 | if (( d_path = decode( targv[ 1 ] )) == NULL ) { 123 | fprintf( stderr, "%d: path too long\n", linenum ); 124 | exit( 2 ); 125 | } 126 | if ( strncmp( d_path, prefix, strlen( prefix )) != 0 ) { 127 | continue; 128 | } 129 | } 130 | 131 | switch ( *targv[ 0 ] ) { 132 | case 'a': 133 | case 'f': 134 | linecheck( line, tac, linenum ); 135 | size += strtoofft( targv[ 6 ], NULL, 10 ); 136 | 137 | default: 138 | size += PROGRESSUNIT; 139 | break; 140 | } 141 | } 142 | 143 | rewind( tran ); 144 | return( size ); 145 | } 146 | 147 | void 148 | progressupdate( ssize_t bytes, char *path ) 149 | { 150 | int last = progress; 151 | 152 | if ( bytes < 0 ) { 153 | return; 154 | } 155 | 156 | total += bytes; 157 | 158 | progress = ( int )((( float )total / ( float )lsize ) * 100 ); 159 | if ( progress > last ) { 160 | printf( "%%%.2d %s\n", progress, path ); 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /progress.h: -------------------------------------------------------------------------------- 1 | #define PROGRESSUNIT 1024 2 | 3 | void linecheck( char *line, int ac, int linenum ); 4 | off_t loadsetsize( FILE *tran ); 5 | off_t applyloadsetsize( FILE *tran ); 6 | off_t lcksum_loadsetsize( FILE *tran, char *prefix ); 7 | void progressupdate( ssize_t bytes, char *path ); 8 | -------------------------------------------------------------------------------- /radstat.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #ifdef __APPLE__ 12 | #include 13 | #include 14 | #endif /* __APPLE__ */ 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #include "applefile.h" 22 | #include "radstat.h" 23 | 24 | /* Return values: 25 | * < 0 system error - errno set 26 | * 0 okay 27 | * 1 error - unknown file type, errno not set 28 | */ 29 | 30 | int 31 | radstat( char *path, struct stat *st, char *type, struct applefileinfo *afinfo ) 32 | { 33 | #ifdef __APPLE__ 34 | static char null_buf[ FINFOLEN ] = { 0 }; 35 | extern struct attrlist getalist; 36 | extern struct attrlist getdiralist; 37 | #endif /* __APPLE__ */ 38 | 39 | if ( lstat( path, st ) != 0 ) { 40 | if (( errno == ENOTDIR ) || ( errno == ENOENT )) { 41 | memset( st, 0, sizeof( struct stat )); 42 | *type = 'X'; 43 | } 44 | return( -1 ); 45 | } 46 | 47 | switch( st->st_mode & S_IFMT ) { 48 | case S_IFREG: 49 | #ifdef __APPLE__ 50 | /* Check to see if it's an HFS+ file */ 51 | if ( afinfo != NULL ) { 52 | if (( getattrlist( path, &getalist, &afinfo->ai, 53 | sizeof( struct attr_info ), FSOPT_NOFOLLOW ) == 0 )) { 54 | if (( afinfo->ai.ai_rsrc_len > 0 ) || 55 | ( memcmp( afinfo->ai.ai_data, null_buf, FINFOLEN ) != 0 )) { 56 | *type = 'a'; 57 | break; 58 | } 59 | } 60 | } 61 | #endif /* __APPLE__ */ 62 | *type = 'f'; 63 | break; 64 | 65 | case S_IFDIR: 66 | #ifdef __APPLE__ 67 | /* Get any finder info */ 68 | if ( afinfo != NULL ) { 69 | getattrlist( path, &getdiralist, &afinfo->ai, 70 | sizeof( struct attr_info ), FSOPT_NOFOLLOW ); 71 | } 72 | #endif /* __APPLE__ */ 73 | *type = 'd'; 74 | break; 75 | 76 | case S_IFLNK: 77 | *type = 'l'; 78 | break; 79 | 80 | case S_IFCHR: 81 | *type = 'c'; 82 | break; 83 | 84 | case S_IFBLK: 85 | *type = 'b'; 86 | break; 87 | 88 | #ifdef sun 89 | case S_IFDOOR: 90 | *type = 'D'; 91 | break; 92 | #endif /* sun */ 93 | 94 | case S_IFIFO: 95 | *type = 'p'; 96 | break; 97 | 98 | case S_IFSOCK: 99 | *type = 's'; 100 | break; 101 | 102 | default: 103 | return ( 1 ); 104 | } 105 | 106 | #ifdef __APPLE__ 107 | /* Calculate full size of applefile */ 108 | if ( *type == 'a' ) { 109 | 110 | /* Finder Info */ 111 | afinfo->as_ents[AS_FIE].ae_id = ASEID_FINFO; 112 | afinfo->as_ents[AS_FIE].ae_offset = AS_HEADERLEN + 113 | ( 3 * sizeof( struct as_entry )); /* 62 */ 114 | afinfo->as_ents[AS_FIE].ae_length = FINFOLEN; 115 | 116 | /* Resource Fork */ 117 | afinfo->as_ents[AS_RFE].ae_id = ASEID_RFORK; 118 | afinfo->as_ents[AS_RFE].ae_offset = /* 94 */ 119 | ( afinfo->as_ents[ AS_FIE ].ae_offset 120 | + afinfo->as_ents[ AS_FIE ].ae_length ); 121 | afinfo->as_ents[ AS_RFE ].ae_length = afinfo->ai.ai_rsrc_len; 122 | 123 | /* Data Fork */ 124 | afinfo->as_ents[AS_DFE].ae_id = ASEID_DFORK; 125 | afinfo->as_ents[ AS_DFE ].ae_offset = 126 | ( afinfo->as_ents[ AS_RFE ].ae_offset 127 | + afinfo->as_ents[ AS_RFE ].ae_length ); 128 | afinfo->as_ents[ AS_DFE ].ae_length = (u_int32_t)st->st_size; 129 | 130 | afinfo->as_size = afinfo->as_ents[ AS_DFE ].ae_offset 131 | + afinfo->as_ents[ AS_DFE ].ae_length; 132 | 133 | /* Set st->st_size to size of encoded apple single file */ 134 | st->st_size = afinfo->as_size; 135 | } 136 | #endif /* __APPLE__ */ 137 | 138 | return( 0 ); 139 | } 140 | -------------------------------------------------------------------------------- /radstat.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | int radstat( char *path, struct stat *st, char *fstype, 7 | struct applefileinfo *afinfo ); 8 | -------------------------------------------------------------------------------- /repo.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006, 2007 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | 26 | #ifdef HAVE_ZLIB 27 | #include 28 | #endif /* HAVE_ZLIB */ 29 | 30 | #include 31 | 32 | #include "code.h" 33 | #include "applefile.h" 34 | #include "connect.h" 35 | #include "report.h" 36 | #include "tls.h" 37 | 38 | int verbose = 0; 39 | void (*logger)( char * ) = NULL; 40 | extern struct timeval timeout; 41 | extern char *version; 42 | extern char *caFile, *caDir, *cert, *privatekey; 43 | SSL_CTX *ctx; 44 | 45 | int 46 | main( int argc, char *argv[] ) 47 | { 48 | SNET *sn; 49 | int c, i = 0, err = 0, len; 50 | int authlevel = _RADMIND_AUTHLEVEL; 51 | int use_randfile = 0; 52 | extern int optind; 53 | unsigned short port = 0; 54 | char *host = _RADMIND_HOST; 55 | char *event = NULL; 56 | char repodata[ MAXPATHLEN * 2 ]; 57 | char **capa = NULL; /* server capabilities */ 58 | 59 | while (( c = getopt( argc, argv, "e:h:p:P:vVw:x:y:Z:z:" )) != EOF ) { 60 | switch ( c ) { 61 | case 'e': /* event to report */ 62 | event = optarg; 63 | break; 64 | 65 | case 'h': 66 | host = optarg; 67 | break; 68 | 69 | case 'p': 70 | /* connect.c handles things if atoi returns 0 */ 71 | port = htons( atoi( optarg )); 72 | break; 73 | 74 | case 'P': 75 | caDir = optarg; 76 | break; 77 | 78 | case 'v': 79 | verbose = 1; 80 | logger = v_logger; 81 | break; 82 | 83 | case 'V': 84 | printf( "%s\n", version ); 85 | exit( 0 ); 86 | 87 | case 'w': 88 | authlevel = atoi( optarg ); 89 | if (( authlevel < 0 ) || ( authlevel > 2 )) { 90 | fprintf( stderr, "%s: invalid authorization level\n", 91 | optarg ); 92 | exit( 2 ); 93 | } 94 | break; 95 | 96 | case 'x': 97 | caFile = optarg; 98 | break; 99 | 100 | case 'y': 101 | cert = optarg; 102 | break; 103 | 104 | case 'z': 105 | privatekey = optarg; 106 | break; 107 | 108 | case 'Z': 109 | #ifdef HAVE_ZLIB 110 | zlib_level = atoi( optarg ); 111 | if (( zlib_level < 0 ) || ( zlib_level > 9 )) { 112 | fprintf( stderr, "Invalid compression level\n" ); 113 | exit( 1 ); 114 | } 115 | break; 116 | #else /* HAVE_ZLIB */ 117 | fprintf( stderr, "Zlib not supported.\n" ); 118 | exit( 1 ); 119 | #endif /* HAVE_ZLIB */ 120 | 121 | default: 122 | err++; 123 | break; 124 | } 125 | } 126 | 127 | /* repo is useless without an event defined */ 128 | if ( event == NULL ) { 129 | err++; 130 | } 131 | 132 | if ( err || (( argc - optind ) < 0 )) { 133 | fprintf( stderr, "usage: %s -e event [ -Vv ] ", argv[ 0 ] ); 134 | fprintf( stderr, "[ -h host ] [ -p port ] [ -P ca-pem-directory ] " ); 135 | fprintf( stderr, "[ -w auth-level ] [ -x ca-pem-file ] " ); 136 | fprintf( stderr, "[ -y cert-pem-file ] [ -z key-pem-file ] " ); 137 | fprintf( stderr, "[ -Z compression-level ] [ message ... ]\n" ); 138 | exit( 1 ); 139 | } 140 | 141 | if ( argc == optind ) { /* read message from stdin */ 142 | if ( fgets( repodata, sizeof( repodata ), stdin ) == NULL ) { 143 | perror( "fgets" ); 144 | exit( 2 ); 145 | } 146 | 147 | len = strlen( repodata ); 148 | if ( repodata[ len - 1 ] != '\n' ) { 149 | fprintf( stderr, "report too long\n" ); 150 | exit( 2 ); 151 | } 152 | repodata[ len - 1 ] = '\0'; 153 | } else { 154 | if ( strlen( argv[ optind ] ) >= sizeof( repodata )) { 155 | fprintf( stderr, "%s: too long\n", argv[ optind ] ); 156 | exit( 2 ); 157 | } 158 | strcpy( repodata, argv[ optind ] ); 159 | 160 | /* Skip first token in message */ 161 | i = 1; 162 | for ( i += optind; i < argc; i++ ) { 163 | if (( strlen( repodata ) + strlen( argv[ i ] ) + 2 ) 164 | >= sizeof( repodata )) { 165 | fprintf( stderr, "%s %s: too long\n", repodata, argv[ i ] ); 166 | exit( 2 ); 167 | } 168 | strcat( repodata, " " ); 169 | strcat( repodata, argv[ i ] ); 170 | } 171 | } 172 | 173 | if (( sn = connectsn( host, port )) == NULL ) { 174 | exit( 2 ); 175 | } 176 | if (( capa = get_capabilities( sn )) == NULL ) { 177 | exit( 2 ); 178 | } 179 | 180 | if ( authlevel != 0 ) { 181 | if ( tls_client_setup( use_randfile, authlevel, caFile, caDir, cert, 182 | privatekey ) != 0 ) { 183 | exit( 2 ); 184 | } 185 | if ( tls_client_start( sn, host, authlevel ) != 0 ) { 186 | exit( 2 ); 187 | } 188 | } 189 | 190 | #ifdef HAVE_ZLIB 191 | /* Enable compression */ 192 | if ( zlib_level > 0 ) { 193 | if ( negotiate_compression( sn, capa ) != 0 ) { 194 | fprintf( stderr, "%s: server does not support reporting\n", host ); 195 | exit( 2 ); 196 | } 197 | } 198 | #endif /* HAVE_ZLIB */ 199 | 200 | /* Check to see if server supports reporting */ 201 | if ( check_capability( "REPO", capa ) == 0 ) { 202 | fprintf( stderr, "%s: server does not support reporting\n", host ); 203 | exit( 2 ); 204 | } 205 | 206 | if ( report_event( sn, event, repodata ) != 0 ) { 207 | exit( 2 ); 208 | } 209 | 210 | if (( closesn( sn )) != 0 ) { 211 | fprintf( stderr, "closesn failed.\n" ); 212 | exit( 2 ); 213 | } 214 | 215 | return( 0 ); 216 | } 217 | -------------------------------------------------------------------------------- /report.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2006, 2007 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #ifdef HAVE_ZLIB 24 | #include 25 | #endif /* HAVE_ZLIB */ 26 | 27 | #include 28 | 29 | #include "code.h" 30 | #include "report.h" 31 | 32 | extern int verbose; 33 | extern void (*logger)( char * ); 34 | extern struct timeval timeout; 35 | 36 | /* 37 | * report_event: report an arbitrary event to the server 38 | * 39 | * return codes: 40 | * 0: event reported 41 | * 1: report failed 42 | */ 43 | int 44 | report_event( SNET *sn, char *event, char *repodata ) 45 | { 46 | struct timeval tv; 47 | char *line; 48 | char *e_repodata; 49 | int i, len; 50 | 51 | /* sanity check the event */ 52 | if ( event == NULL ) { 53 | fprintf( stderr, "report_event: event must be non-NULL\n" ); 54 | return( 1 ); 55 | } 56 | if (( len = strlen( event )) == 0 ) { 57 | fprintf( stderr, "report_event: invalid zero-length event\n" ); 58 | return( 1 ); 59 | } else { 60 | for ( i = 0; i < len; i++ ) { 61 | if ( isspace(( int )event[ i ] )) { 62 | fprintf( stderr, "report_event: event must not " 63 | "contain whitespace\n" ); 64 | return( 1 ); 65 | } 66 | } 67 | } 68 | 69 | if (( e_repodata = encode( repodata )) == NULL ) { 70 | fprintf( stderr, "report_event: encode: buffer too small\n" ); 71 | return( 1 ); 72 | } 73 | 74 | if ( snet_writef( sn, "REPO %s %s\r\n", event, e_repodata ) < 0 ) { 75 | perror( "snet_writef" ); 76 | return( 1 ); 77 | } 78 | if ( verbose ) printf( ">>> REPO %s %s\n", event, e_repodata ); 79 | 80 | tv = timeout; 81 | if (( line = snet_getline_multi( sn, logger, &tv )) == NULL ) { 82 | perror( "snet_getline_multi" ); 83 | return( 1 ); 84 | } 85 | if ( *line != '2' ) { 86 | fprintf( stderr, "%s\n", line ); 87 | return( 1 ); 88 | } 89 | 90 | return( 0 ); 91 | } 92 | 93 | /* 94 | * report_error_and_exit: report an error and exit with the give value 95 | */ 96 | void 97 | report_error_and_exit( SNET *sn, char *event, char *repodata, int rc ) 98 | { 99 | ( void )report_event( sn, event, repodata ); 100 | 101 | exit( rc ); 102 | } 103 | -------------------------------------------------------------------------------- /report.h: -------------------------------------------------------------------------------- 1 | int report_event( SNET *sn, char *event, char *repodata ); 2 | void report_error_and_exit( SNET *sn, char *event, char *repodata, int rc ); 3 | -------------------------------------------------------------------------------- /rmdirs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "rmdirs.h" 18 | 19 | int 20 | rmdirs( char *path ) 21 | { 22 | int i, len, unlinkedfiles; 23 | char temp[ MAXPATHLEN ]; 24 | DIR *dir; 25 | struct dirent *dirent; 26 | struct stat st; 27 | 28 | if (( dir = opendir( path )) == NULL ) { 29 | return( -1 ); 30 | } 31 | 32 | /* readdir() on HFS+ is broken: 33 | * http://docs.info.apple.com/article.html?artnum=107884 34 | * 35 | * "The unspecified behavior is what readdir() should return after the 36 | * directory has been modified. Many file systems have been implemented 37 | * such that subsequent readdir() calls will return the next directory 38 | * entry. The implementation of the HFS file system cannot guarantee 39 | * that all enclosed files or directories will be removed using the 40 | * above method." 41 | */ 42 | 43 | do { 44 | unlinkedfiles = 0; 45 | 46 | while (( dirent = readdir( dir )) != NULL ) { 47 | 48 | /* don't include . and .. */ 49 | if (( strcmp( dirent->d_name, "." ) == 0 ) || 50 | ( strcmp( dirent->d_name, ".." ) == 0 )) { 51 | continue; 52 | } 53 | 54 | len = strlen( path ); 55 | 56 | /* absolute pathname. add 2 for / and NULL termination. */ 57 | if (( len + strlen( dirent->d_name ) + 2 ) > MAXPATHLEN ) { 58 | fprintf( stderr, "Absolute pathname too long\n" ); 59 | goto error; 60 | } 61 | 62 | if ( path[ len - 1 ] == '/' ) { 63 | if ( snprintf( temp, MAXPATHLEN, "%s%s", path, dirent->d_name ) 64 | >= MAXPATHLEN ) { 65 | fprintf( stderr, "%s%s: path too long\n", path, 66 | dirent->d_name ); 67 | goto error; 68 | } 69 | } else { 70 | if ( snprintf( temp, MAXPATHLEN, "%s/%s", path, dirent->d_name ) 71 | >= MAXPATHLEN ) { 72 | fprintf( stderr, "%s/%s: path too long\n", path, 73 | dirent->d_name ); 74 | goto error; 75 | } 76 | } 77 | 78 | if ( lstat( temp, &st ) != 0 ) { 79 | /* XXX - how to return path that gave error? */ 80 | fprintf( stderr, "%s: %s\n", temp, strerror( errno )); 81 | goto error; 82 | } 83 | if ( S_ISDIR( st.st_mode )) { 84 | if ( rmdirs( temp ) != 0 ) { 85 | fprintf( stderr, "%s: %s\n", temp, strerror( errno )); 86 | goto error; 87 | } 88 | } else { 89 | if ( unlink( temp ) != 0 ) { 90 | fprintf( stderr, "%s: %s\n", temp, strerror( errno )); 91 | goto error; 92 | } 93 | unlinkedfiles = 1; 94 | } 95 | if ( unlinkedfiles ) { 96 | rewinddir( dir ); 97 | } 98 | } 99 | } while ( unlinkedfiles ); 100 | 101 | if ( closedir( dir ) != 0 ) { 102 | return( -1 ); 103 | } 104 | if ( rmdir( path ) != 0 ) { 105 | return( -1 ); 106 | } 107 | 108 | return ( 0 ); 109 | 110 | error: 111 | i = errno; 112 | if ( closedir( dir ) != 0 ) { 113 | errno = i; 114 | } 115 | return( -1 ); 116 | } 117 | -------------------------------------------------------------------------------- /rmdirs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | int rmdirs( char *path ); 7 | -------------------------------------------------------------------------------- /root.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "root.h" 10 | 11 | int 12 | get_root( char *radmind_path, char *path, char *file_root, char *tran_root, char *tran_name ) 13 | { 14 | char real_path[ PATH_MAX ]; 15 | char test_path[ MAXPATHLEN ]; 16 | char radmind_real_path[ PATH_MAX ]; 17 | char *p; 18 | 19 | if ( realpath( radmind_path, radmind_real_path ) == NULL ) { 20 | perror( radmind_real_path ); 21 | return( -1 ); 22 | } 23 | if ( realpath( path, real_path ) == NULL ) { 24 | perror( real_path ); 25 | return( -1 ); 26 | } 27 | 28 | /* Get transcript name */ 29 | if (( p = strrchr( real_path, '/' )) == real_path ) { 30 | fprintf( stderr, "%s: invalid transcript location\n", real_path ); 31 | return( -1 ); 32 | } 33 | *p++ = '\0'; 34 | if ( strlen( p ) >= MAXPATHLEN ) { 35 | fprintf( stderr, "%s: path too long\n", p ); 36 | return( -1 ); 37 | } 38 | strcpy( tran_name, p ); 39 | 40 | if ( snprintf( test_path, MAXPATHLEN, "%s/tmp/transcript", 41 | radmind_real_path ) >= MAXPATHLEN ) { 42 | fprintf( stderr, "%s/tmp/transcirpt: path too long\n", 43 | radmind_real_path ); 44 | return( -1 ); 45 | } 46 | 47 | if ( strstr( real_path, test_path ) != NULL ) { 48 | if ( snprintf( file_root, MAXPATHLEN, "%s/tmp/file%s", 49 | radmind_real_path, &real_path[ strlen( test_path ) ]) 50 | >= MAXPATHLEN ) { 51 | fprintf( stderr, "%s/tmp/file%s: path too long\n", 52 | radmind_real_path, &real_path[ strlen( test_path )] ); 53 | return( -1 ); 54 | } 55 | if ( snprintf( tran_root, MAXPATHLEN, "%s/tmp/transcript%s", 56 | radmind_real_path, &real_path[ strlen( test_path ) ]) 57 | >= MAXPATHLEN ) { 58 | fprintf( stderr, "%s/tmp/transcript%s: path too long\n", 59 | radmind_real_path, &real_path[ strlen( test_path )] ); 60 | return( -1 ); 61 | } 62 | } else { 63 | if ( snprintf( test_path, MAXPATHLEN, "%s/transcript", 64 | radmind_real_path ) >= MAXPATHLEN ) { 65 | fprintf( stderr, "%s/transcript: path too long\n", 66 | radmind_real_path ); 67 | return( -1 ); 68 | } 69 | 70 | if ( strstr( real_path, test_path ) != NULL ) { 71 | if ( snprintf( file_root, MAXPATHLEN, "%s/file%s", 72 | radmind_real_path, &real_path[ strlen( test_path ) ]) 73 | >= MAXPATHLEN ) { 74 | fprintf( stderr, "%s/file%s: path too long\n", 75 | radmind_real_path, &real_path[ strlen( test_path ) ]); 76 | return( -1 ); 77 | } 78 | if ( snprintf( tran_root, MAXPATHLEN, "%s/transcript%s", 79 | radmind_real_path, &real_path[ strlen( test_path ) ]) 80 | >= MAXPATHLEN ) { 81 | fprintf( stderr, "%s/transcript%s: path too long\n", 82 | radmind_real_path, &real_path[ strlen( test_path )] ); 83 | return( -1 ); 84 | } 85 | } else { 86 | if ( snprintf( file_root, MAXPATHLEN, "%s/../file", 87 | real_path ) >= MAXPATHLEN ) { 88 | fprintf( stderr, "%s/../file: path too long\n", 89 | real_path); 90 | return( -1); 91 | } 92 | snprintf( tran_root, MAXPATHLEN, "%s", real_path ); 93 | } 94 | } 95 | 96 | return( 0 ); 97 | } 98 | -------------------------------------------------------------------------------- /root.h: -------------------------------------------------------------------------------- 1 | int get_root( char *radmind_path, char *path, char *file_root, char *tran_root, char *tran_name ); 2 | -------------------------------------------------------------------------------- /tls.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | int tls_server_setup( int use_randfile, int authlevel, char *caFile, char *caDir, char *crlFile, char *crlDir, char *cert, char *privatekey ); 7 | int tls_client_setup( int use_randfile, int authlevel, char *caFile, char *caDir, char *cert, char *privatekey ); 8 | int tls_client_start( SNET *sn, char *host, int authlevel ); 9 | -------------------------------------------------------------------------------- /transcript.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | #include 7 | 8 | #define T_NULL 0 9 | #define T_POSITIVE 1 10 | #define T_NEGATIVE 2 11 | #define T_SPECIAL 3 12 | 13 | #define T_RELATIVE 0 14 | #define T_ABSOLUTE 1 15 | 16 | #define T_MOVE_TRAN 1 17 | #define T_MOVE_FS 2 18 | #define T_MOVE_BOTH 3 19 | 20 | #define T_MODE 0x0FFF 21 | 22 | #define APPLICABLE 0 23 | #define CREATABLE 1 24 | 25 | #define PR_TRAN_ONLY 1 26 | #define PR_FS_ONLY 2 27 | #define PR_DOWNLOAD 3 28 | #define PR_STATUS 4 29 | #define PR_STATUS_NEG 5 30 | #define PR_STATUS_MINUS 6 31 | 32 | #define K_CLIENT 0 33 | #define K_SERVER 1 34 | 35 | extern int edit_path; 36 | extern int skip; 37 | extern int cksum; 38 | extern int fs_minus; 39 | extern FILE *outtran; 40 | extern char *path_prefix; 41 | 42 | 43 | #define T_SKIP_POSITIVE (1 << 1) 44 | #define T_SKIP_NEGATIVE (1 << 2) 45 | #define T_SKIP_SPECIAL (1 << 3) 46 | #define T_SKIP_EXCLUDES (1 << 4) 47 | #define T_SKIP_ALL (T_SKIP_POSITIVE | T_SKIP_NEGATIVE | \ 48 | T_SKIP_SPECIAL | T_SKIP_EXCLUDES) 49 | 50 | struct pathinfo { 51 | char pi_type; 52 | int pi_minus; 53 | char pi_name[ MAXPATHLEN ]; 54 | char pi_link[ MAXPATHLEN ]; 55 | struct stat pi_stat; 56 | char pi_cksum_b64[ MAXPATHLEN ]; 57 | struct applefileinfo pi_afinfo; 58 | }; 59 | 60 | struct transcript { 61 | struct transcript *t_next; 62 | struct transcript *t_prev; 63 | struct pathinfo t_pinfo; 64 | int t_type; 65 | int t_num; 66 | char t_fullname[ MAXPATHLEN ]; 67 | char t_shortname[ MAXPATHLEN ]; 68 | char t_kfile[ MAXPATHLEN ]; 69 | int t_linenum; 70 | int t_eof; 71 | FILE *t_in; 72 | }; 73 | 74 | int transcript( char *, struct stat *, char *, struct applefileinfo *, int ); 75 | void transcript_init( char *kfile, int location ); 76 | struct transcript *transcript_select( void ); 77 | void transcript_parse( struct transcript * ); 78 | void transcript_free( void ); 79 | void t_new( int, char *, char *, char * ); 80 | int t_exclude( char *path ); 81 | void t_print( struct pathinfo *, struct transcript *, int ); 82 | char *hardlink( struct pathinfo * ); 83 | int hardlink_changed( struct pathinfo *, int ); 84 | void hardlink_free( void ); 85 | -------------------------------------------------------------------------------- /twhich.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #include "applefile.h" 17 | #include "transcript.h" 18 | #include "code.h" 19 | #include "pathcmp.h" 20 | #include "list.h" 21 | #include "wildcard.h" 22 | 23 | const EVP_MD *md; 24 | 25 | int case_sensitive = 1; 26 | int tran_format = -1; 27 | 28 | /* 29 | * exit codes: 30 | * 0 File found 31 | * 1 File not found. 32 | * >1 An error occurred. 33 | */ 34 | 35 | static int 36 | twhich( char *pattern, int displayall ) 37 | { 38 | struct node *node; 39 | struct transcript *tran; 40 | extern struct transcript *tran_head; 41 | extern struct list *exclude_list; 42 | int cmp = 0, match = 0; 43 | 44 | /* check exclude list */ 45 | if ( exclude_list->l_count > 0 ) { 46 | for ( node = list_pop_head( exclude_list ); node != NULL; 47 | node = list_pop_head( exclude_list )) { 48 | if ( wildcard( node->n_path, pattern, case_sensitive )) { 49 | printf( "# Exclude\n" ); 50 | printf( "# exclude pattern: %s\n", node->n_path ); 51 | if ( !displayall ) { 52 | goto done; 53 | } 54 | } 55 | free( node ); 56 | } 57 | } 58 | 59 | for ( tran = tran_head; tran->t_next != NULL; tran = tran->t_next ) { 60 | 61 | /* Skip NULL/empty transcripts */ 62 | if ( tran->t_eof ) { 63 | continue; 64 | } 65 | 66 | while (( cmp = pathcasecmp( tran->t_pinfo.pi_name, 67 | pattern, case_sensitive )) < 0 ) { 68 | transcript_parse( tran ); 69 | if ( tran->t_eof ) { 70 | break; 71 | } 72 | } 73 | if ( tran->t_eof ) { 74 | continue; 75 | } 76 | 77 | if ( cmp > 0 ) { 78 | continue; 79 | } 80 | 81 | if ( cmp == 0 ) { 82 | match++; 83 | switch( tran->t_type ) { 84 | case T_POSITIVE: 85 | printf( "# Positive\n" ); 86 | break; 87 | 88 | case T_NEGATIVE: 89 | printf( "# Negative\n" ); 90 | break; 91 | 92 | case T_SPECIAL: 93 | printf( "# Special\n" ); 94 | break; 95 | 96 | default: 97 | fprintf( stderr, "unknown transcript type\n" ); 98 | exit( 2 ); 99 | } 100 | printf( "# %s:\n", tran->t_kfile ); 101 | 102 | if ( tran->t_pinfo.pi_minus ) { 103 | printf( "%s:\n", tran->t_shortname ); 104 | t_print( NULL, tran, PR_STATUS_MINUS ); 105 | } else { 106 | t_print( NULL, tran, PR_TRAN_ONLY ); 107 | } 108 | 109 | if ( !displayall ) { 110 | goto done; 111 | } 112 | } 113 | } 114 | 115 | done: 116 | if ( match ) { 117 | return( 0 ); 118 | } else { 119 | return( 1 ); 120 | } 121 | } 122 | 123 | int 124 | main( int argc, char **argv ) 125 | { 126 | int c, err = 0, defaultkfile = 1, rc = 0, len; 127 | int server = 0, displayall = 0, recursive = 0; 128 | extern char *version; 129 | char *kfile = _RADMIND_COMMANDFILE; 130 | char *pattern, *p; 131 | 132 | while (( c = getopt( argc, argv, "aIK:rsV" )) != EOF ) { 133 | switch( c ) { 134 | case 'a': 135 | displayall = 1; 136 | break; 137 | 138 | case 'K': 139 | defaultkfile = 0; 140 | kfile = optarg; 141 | break; 142 | 143 | case 'I': 144 | case_sensitive = 0; 145 | break; 146 | 147 | case 'r': /* recursively twhich all path elements */ 148 | recursive = 1; 149 | break; 150 | 151 | case 's': 152 | server = 1; 153 | break; 154 | 155 | case 'V': 156 | printf( "%s\n", version ); 157 | exit( 0 ); 158 | 159 | default: 160 | err++; 161 | break; 162 | } 163 | } 164 | 165 | if (( argc - optind ) != 1 ) { 166 | err++; 167 | } 168 | 169 | pattern = argv[ argc - 1 ]; 170 | len = strlen( pattern ); 171 | 172 | if ( server && defaultkfile ) { 173 | err++; 174 | } 175 | 176 | if ( err ) { 177 | fprintf( stderr, "Usage: %s [ -aIrV ] [ -K command file ] file\n", 178 | argv[ 0 ] ); 179 | fprintf( stderr, "Usage: %s -s -K command [ -aIrV ] file\n", 180 | argv[ 0 ] ); 181 | exit( 2 ); 182 | } 183 | 184 | /* clip trailing slash */ 185 | if ( len > 1 && pattern[ len - 1 ] == '/' ) { 186 | pattern[ len - 1 ] = '\0'; 187 | len--; 188 | } 189 | 190 | /* Determine if called with relative or absolute pathing. Path is relative 191 | * if it's just '.' or starts with './'. File names that start with a '.' 192 | * are absolute. 193 | */ 194 | if ( pattern[ 0 ] == '.' ) { 195 | if ( len == 1 ) { 196 | tran_format = T_RELATIVE; 197 | } else if ( pattern[ 1 ] == '/' ) { 198 | tran_format = T_RELATIVE; 199 | } 200 | } else { 201 | tran_format = T_ABSOLUTE; 202 | } 203 | 204 | /* initialize the transcripts */ 205 | edit_path = APPLICABLE; 206 | if ( server ) { 207 | transcript_init( kfile, K_SERVER ); 208 | } else { 209 | transcript_init( kfile, K_CLIENT ); 210 | } 211 | outtran = stdout; 212 | 213 | if ( recursive ) { 214 | for ( p = pattern; *p == '/'; p++ ) 215 | ; 216 | for ( p = strchr( p, '/' ); p != NULL; p = strchr( p, '/' )) { 217 | *p = '\0'; 218 | if ( twhich( pattern, displayall ) != 0 ) { 219 | printf( "# %s: not found\n", pattern ); 220 | } 221 | 222 | *p++ = '/'; 223 | } 224 | } 225 | rc = twhich( pattern, displayall ); 226 | 227 | exit( rc ); 228 | } 229 | -------------------------------------------------------------------------------- /update.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #ifdef MAJOR_IN_SYSMACROS 13 | #include 14 | #endif 15 | #ifdef MAJOR_IN_MKDEV 16 | #include 17 | #endif 18 | 19 | #ifdef __APPLE__ 20 | #include 21 | #endif /* __APPLE__ */ 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "applefile.h" 30 | #include "base64.h" 31 | #include "update.h" 32 | #include "code.h" 33 | #include "radstat.h" 34 | #include "largefile.h" 35 | #include "transcript.h" 36 | #include "progress.h" 37 | #include "mkdirs.h" 38 | #include "mkprefix.h" 39 | 40 | extern int quiet; 41 | extern int linenum; 42 | extern int showprogress; 43 | extern int create_prefix; 44 | 45 | /* 46 | * lchmod is only available on Mac OS X 10.5 47 | * right now. we use weak linking to avoid 48 | * two different builds for 10.4 and 10.5. 49 | */ 50 | #ifdef HAVE_LCHMOD 51 | extern int lchmod( const char *, mode_t ) __attribute__(( weak )); 52 | #endif /* HAVE_LCHMOD */ 53 | 54 | int 55 | update( char *path, char *displaypath, int present, int newfile, 56 | struct stat *st, int tac, char **targv, struct applefileinfo *afinfo ) 57 | { 58 | int timeupdated = 0; 59 | mode_t mode; 60 | struct utimbuf times; 61 | uid_t uid; 62 | gid_t gid; 63 | dev_t dev; 64 | char type; 65 | char *d_target; 66 | #ifdef __APPLE__ 67 | unsigned char fi_data[ SZ_BASE64_D( SZ_BASE64_E( FINFOLEN ) ) ]; 68 | extern struct attrlist setalist; 69 | static char null_buf[ SZ_BASE64_D( SZ_BASE64_E( FINFOLEN ) ) ] = { 0 }; 70 | #endif /* __APPLE__ */ 71 | 72 | switch ( *targv[ 0 ] ) { 73 | case 'a': 74 | case 'f': 75 | if ( tac != 8 ) { 76 | fprintf( stderr, "%d: incorrect number of arguments\n", linenum ); 77 | return( 1 ); 78 | } 79 | 80 | mode = strtol( targv[ 2 ], (char **)NULL, 8 ); 81 | 82 | times.modtime = strtotimet( targv[ 5 ], NULL, 10 ); 83 | if ( times.modtime != st->st_mtime ) { 84 | times.actime = st->st_atime; 85 | if ( utime( path, × ) != 0 ) { 86 | perror( path ); 87 | return( 1 ); 88 | } 89 | timeupdated = 1; 90 | } 91 | break; 92 | 93 | case 'd': 94 | if (( tac != 5 ) 95 | #ifdef __APPLE__ 96 | && ( tac != 6 ) 97 | #endif /* __APPLE__ */ 98 | ) { 99 | fprintf( stderr, 100 | "%d: incorrect number of arguments\n", linenum ); 101 | return( 1 ); 102 | } 103 | 104 | mode = strtol( targv[ 2 ], (char **)NULL, 8 ); 105 | 106 | if ( !present ) { 107 | if ( mkdir( path, mode ) != 0 ) { 108 | if ( create_prefix && errno == ENOENT ) { 109 | errno = 0; 110 | if ( mkprefix( path ) != 0 ) { 111 | perror( path ); 112 | return( 1 ); 113 | } 114 | if ( mkdir( path, mode ) != 0 ) { 115 | perror( path ); 116 | return( 1 ); 117 | } 118 | } else { 119 | perror( path ); 120 | return( 1 ); 121 | } 122 | } 123 | newfile = 1; 124 | if ( radstat( (char*)path, st, &type, afinfo ) < 0 ) { 125 | perror( path ); 126 | return( 1 ); 127 | } 128 | present = 1; 129 | } 130 | 131 | #ifdef __APPLE__ 132 | /* Check finder info */ 133 | if ( tac == 6 ) { 134 | memset( fi_data, 0, FINFOLEN ); 135 | base64_d( targv[ 5 ], strlen( targv[ 5 ] ), fi_data ); 136 | } else { 137 | memcpy( fi_data, null_buf, FINFOLEN ); 138 | } 139 | if ( memcmp( afinfo->ai.ai_data, fi_data, FINFOLEN ) != 0 ) { 140 | if ( setattrlist( path, &setalist, 141 | fi_data, FINFOLEN, FSOPT_NOFOLLOW ) != 0 ) { 142 | fprintf( stderr, 143 | "retrieve %s failed: Could not set Finder Info attribute\n", path ); 144 | return( -1 ); 145 | } 146 | } 147 | #endif /* __APPLE__ */ 148 | break; 149 | 150 | case 'h': 151 | if ( tac != 3 ) { 152 | fprintf( stderr, 153 | "%d: incorrect number of arguments\n", linenum ); 154 | return( 1 ); 155 | } 156 | if (( d_target = decode( targv[ 2 ] )) == NULL ) { 157 | fprintf( stderr, "line %d: target path too long\n", linenum ); 158 | return( 1 ); 159 | } 160 | if ( link( d_target, path ) != 0 ) { 161 | if ( create_prefix && errno == ENOENT ) { 162 | errno = 0; 163 | if ( mkprefix( path ) != 0 ) { 164 | perror( path ); 165 | return( 1 ); 166 | } 167 | if ( link( d_target, path ) != 0 ) { 168 | perror( path ); 169 | return( 1 ); 170 | } 171 | } else { 172 | perror( path ); 173 | return( 1 ); 174 | } 175 | } 176 | if ( !quiet && !showprogress ) { 177 | printf( "%s: hard linked to %s", displaypath, d_target); 178 | } 179 | goto done; 180 | 181 | case 'l': 182 | if ( tac == 3 ) { 183 | /* legacy symlink entries get defaults */ 184 | mode = ( mode_t )0777; 185 | uid = 0; 186 | gid = 0; 187 | } else if ( tac == 6 ) { 188 | /* symlink with mode, uid, gid */ 189 | mode = ( mode_t )strtol( targv[ 2 ], NULL, 8 ); 190 | uid = atoi( targv[ 3 ] ); 191 | gid = atoi( targv[ 4 ] ); 192 | } else { 193 | fprintf( stderr, "%d: incorrect number of arguments\n", linenum ); 194 | return( 1 ); 195 | } 196 | if ( present ) { 197 | if ( unlink( path ) != 0 ) { 198 | perror( path ); 199 | return( 1 ); 200 | } 201 | present = 0; 202 | } 203 | if (( d_target = decode( targv[ tac - 1 ] )) == NULL ) { 204 | fprintf( stderr, "line %d: target path too long\n", linenum ); 205 | return( 1 ); 206 | } 207 | if ( symlink( d_target, path ) != 0 ) { 208 | if ( create_prefix && errno == ENOENT ) { 209 | errno = 0; 210 | if ( mkprefix( path ) != 0 ) { 211 | perror( path ); 212 | return( 1 ); 213 | } 214 | if ( symlink( d_target, path ) != 0 ) { 215 | perror( path ); 216 | return( 1 ); 217 | } 218 | } else { 219 | perror( path ); 220 | return( 1 ); 221 | } 222 | } 223 | if ( !quiet && !showprogress ) { 224 | printf( "%s: symbolic linked to %s", displaypath, d_target ); 225 | } 226 | #if defined( HAVE_LCHOWN ) || defined( HAVE_LCHMOD ) 227 | if ( !quiet && !showprogress ) { 228 | printf( " updating" ); 229 | } 230 | #ifdef HAVE_LCHOWN 231 | if ( uid != st->st_uid || gid != st->st_gid ) { 232 | if ( lchown( path, uid, gid ) != 0 ) { 233 | perror( path ); 234 | return( 1 ); 235 | } 236 | } 237 | if ( uid != st->st_uid && !quiet && !showprogress ) { 238 | printf( " uid" ); 239 | } 240 | if ( gid != st->st_gid && !quiet && !showprogress ) { 241 | printf( " gid" ); 242 | } 243 | #endif /* HAVE_LCHOWN */ 244 | 245 | #ifdef HAVE_LCHMOD 246 | /* 247 | * if we compiled with weak linking and lchmod 248 | * isn't in the library, the symbol may be NULL. 249 | */ 250 | if ( lchmod != NULL ) { 251 | if (( mode != ( T_MODE & st->st_mode )) || 252 | (( uid != st->st_uid || gid != st->st_gid ) && 253 | (( mode & ( S_ISUID | S_ISGID )) != 0 ))) { 254 | if ( lchmod( path, mode ) != 0 ) { 255 | perror( path ); 256 | return( 1 ); 257 | } 258 | if ( !quiet && !showprogress ) { 259 | printf( " mode" ); 260 | } 261 | } 262 | } 263 | #endif /* HAVE_LCHMOD */ 264 | #endif /* defined( HAVE_LCHOWN ) || defined( HAVE_LCHMOD ) */ 265 | goto done; 266 | 267 | case 'p': 268 | if ( tac != 5 ) { 269 | fprintf( stderr, 270 | "%d: incorrect number of arguments\n", linenum ); 271 | return( 1 ); 272 | } 273 | 274 | mode = strtol( targv[ 2 ], (char **)NULL, 8 ) | S_IFIFO; 275 | 276 | if ( !present ) { 277 | if ( mkfifo( path, mode ) != 0 ){ 278 | if ( create_prefix && errno == ENOENT ) { 279 | errno = 0; 280 | if ( mkprefix( path ) != 0 ) { 281 | perror( path ); 282 | return( 1 ); 283 | } 284 | if ( mkfifo( path, mode ) != 0 ) { 285 | perror( path ); 286 | return( 1 ); 287 | } 288 | } else { 289 | perror( path ); 290 | return( 1 ); 291 | } 292 | } 293 | if ( lstat( path, st ) != 0 ) { 294 | perror( path ); 295 | return( 1 ); 296 | } 297 | present = 1; 298 | newfile = 1; 299 | } 300 | break; 301 | 302 | case 'b': 303 | case 'c': 304 | if ( tac != 7 ) { 305 | fprintf( stderr, 306 | "%d: incorrect number of arguments\n", linenum ); 307 | return( 1 ); 308 | } 309 | 310 | mode = strtol( targv[ 2 ], (char **)NULL, 8 ); 311 | 312 | if ( present && (( minor( st->st_rdev ) != atoi( targv[ 6 ] )) || 313 | ( major( st->st_rdev ) != atoi( targv[ 5 ] )))) { 314 | if ( unlink( path ) != 0 ) { 315 | perror( path ); 316 | return( 1 ); 317 | } 318 | present = 0; 319 | } 320 | 321 | if ( !present ) { 322 | #ifdef sun 323 | if ( ( dev = makedev( (major_t)atoi( targv[ 5 ] ), 324 | (minor_t)atoi( targv[ 6 ] ) ) ) == NODEV ) { 325 | perror( path ); 326 | return( 1 ); 327 | } 328 | #else /* !sun */ 329 | dev = makedev( atoi( targv[ 5 ] ), atoi( targv[ 6 ] )); 330 | #endif /* sun */ 331 | 332 | if( *targv[ 0 ] == 'b' ) { 333 | mode |= S_IFBLK; 334 | } else { 335 | mode |= S_IFCHR; 336 | } 337 | 338 | if ( mknod( path, mode, dev ) != 0 ) { 339 | if ( create_prefix && errno == ENOENT ) { 340 | errno = 0; 341 | if ( mkprefix( path ) != 0 ) { 342 | perror( path ); 343 | return( 1 ); 344 | } 345 | if ( mknod( path, mode, dev ) != 0 ) { 346 | perror( path ); 347 | return( 1 ); 348 | } 349 | } else { 350 | perror( path ); 351 | return( 1 ); 352 | } 353 | } 354 | if ( lstat( path, st ) != 0 ) { 355 | perror( path ); 356 | return( 1 ); 357 | } 358 | present = 1; 359 | newfile = 1; 360 | } 361 | break; 362 | 363 | case 's': 364 | case 'D': 365 | if ( tac != 5 ) { 366 | fprintf( stderr, 367 | "%d: incorrect number of arguments\n", linenum ); 368 | return( 1 ); 369 | } 370 | 371 | mode = strtol( targv[ 2 ], (char **)NULL, 8 ); 372 | 373 | if ( !present ) { 374 | fprintf( stderr, "%d: Warning: %c %s not created...continuing\n", 375 | linenum, *targv[ 0 ], path ); 376 | return( 2 ); 377 | } 378 | 379 | break; 380 | 381 | default : 382 | fprintf( stderr, "%d: Unknown type %s\n", linenum, targv[ 0 ] ); 383 | return( 1 ); 384 | } 385 | 386 | if ( !quiet && !showprogress ) { 387 | if ( newfile ) { 388 | printf( "%s: created updating", displaypath ); 389 | } else { 390 | printf( "%s: updating", displaypath ); 391 | } 392 | } 393 | 394 | /* check uid & gid */ 395 | uid = atoi( targv[ 3 ] ); 396 | gid = atoi( targv[ 4 ] ); 397 | if ( uid != st->st_uid || gid != st->st_gid ) { 398 | if ( chown( path, uid, gid ) != 0 ) { 399 | perror( path ); 400 | return( 1 ); 401 | } 402 | if ( uid != st->st_uid ) { 403 | if ( !quiet && !showprogress ) printf( " uid" ); 404 | } 405 | if ( gid != st->st_gid ) { 406 | if ( !quiet && !showprogress ) printf( " gid" ); 407 | } 408 | } 409 | /* 410 | * chmod after chown to preserve S_ISUID and S_ISGID mode bits 411 | * We also need an extra chmod if we did a chown on a set-uid or -gid 412 | * file. 413 | */ 414 | if (( mode != ( T_MODE & st->st_mode )) || 415 | (( uid != st->st_uid || gid != st->st_gid ) && 416 | (( mode & ( S_ISUID | S_ISGID )) != 0 ))) { 417 | if ( chmod( path, mode ) != 0 ) { 418 | perror( path ); 419 | return( 1 ); 420 | } 421 | if ( !quiet && !showprogress ) printf( " mode" ); 422 | } 423 | 424 | if ( timeupdated && !showprogress && !quiet ) { 425 | printf( " time" ); 426 | } 427 | 428 | done: 429 | if ( !quiet && !showprogress ) printf( "\n" ); 430 | if ( showprogress ) { 431 | progressupdate( PROGRESSUNIT, displaypath ); 432 | } 433 | 434 | return( 0 ); 435 | } 436 | -------------------------------------------------------------------------------- /update.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | int update( char *path, char *displaypath, int present, int newfile, 7 | struct stat *st, int tac, char **targv, struct applefileinfo *afinfo ); 8 | -------------------------------------------------------------------------------- /version.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | #include "config.h" 7 | 8 | char *version = VERSION; 9 | char *checksumlist = "sha1\nsha\nmd5\nmd2\ndss1\nmdc2\nripemd160"; 10 | -------------------------------------------------------------------------------- /wildcard.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | #include "config.h" 7 | 8 | #include 9 | #include 10 | 11 | #include "wildcard.h" 12 | 13 | int 14 | wildcard( char *wild, char *p, int sensitive ) 15 | { 16 | int min, max; 17 | int i, len; 18 | char *comma, *end; 19 | 20 | for (;;) { 21 | switch ( *wild ) { 22 | case '*' : 23 | wild++; 24 | 25 | if ( *wild == '\0' ) { 26 | return( 1 ); 27 | } 28 | for ( i = 0; p[ i ] != '\0'; i++ ) { 29 | if ( wildcard( wild, &p[ i ], sensitive )) { 30 | return( 1 ); 31 | } 32 | } 33 | return( 0 ); 34 | 35 | case '<' : 36 | wild++; 37 | 38 | if ( ! isdigit( (int)*p )) { 39 | return( 0 ); 40 | } 41 | i = atoi( p ); 42 | while ( isdigit( (int)*p )) p++; 43 | 44 | if ( ! isdigit( (int)*wild )) { 45 | return( 0 ); 46 | } 47 | min = atoi( wild ); 48 | while ( isdigit( (int)*wild )) wild++; 49 | 50 | if ( *wild++ != '-' ) { 51 | return( 0 ); 52 | } 53 | 54 | if ( ! isdigit( (int)*wild )) { 55 | return( 0 ); 56 | } 57 | max = atoi( wild ); 58 | while ( isdigit( (int)*wild )) wild++; 59 | 60 | if ( *wild++ != '>' ) { 61 | return( 0 ); 62 | } 63 | 64 | if (( i < min ) || ( i > max )) { 65 | return( 0 ); 66 | } 67 | break; 68 | 69 | case '?' : 70 | wild++; 71 | p++; 72 | break; 73 | 74 | case '[' : 75 | for ( wild++; *wild != ']'; wild++ ) { 76 | if ( sensitive ) { 77 | if ( *wild != *p ) break; 78 | } else { 79 | if ( tolower(*wild) != tolower(*p) ) break; 80 | } 81 | } 82 | if ( *wild == ']' ) { 83 | return( 0 ); 84 | } 85 | for ( ; *wild; wild++ ) { 86 | if ( *wild == ']' ) { 87 | break; 88 | } 89 | } 90 | if ( *wild == '\0' ) { 91 | return( 0 ); 92 | } 93 | 94 | p++; 95 | wild++; 96 | break; 97 | 98 | case '{' : 99 | comma = wild; 100 | 101 | for ( end = wild + 1; *end != '}'; end++ ) { 102 | if ( *end == '{' || *end == '\0' ) { 103 | /* malformed pattern */ 104 | return( 0 ); 105 | } 106 | } 107 | end++; 108 | 109 | do { 110 | for ( wild = ++comma; *comma != ',' && *comma != '}'; comma++ ) 111 | ; 112 | len = comma - wild; 113 | 114 | for ( i = 0; i < len; i++ ) { 115 | if ( sensitive ) { 116 | if ( wild[ i ] != p[ i ] ) break; 117 | } else { 118 | if ( tolower( wild[ i ] ) != tolower( p[ i ] )) break; 119 | } 120 | } 121 | if ( i >= len && wildcard( end, &p[ i ], sensitive )) { 122 | return( 1 ); 123 | } 124 | } while ( *comma != '}' ); 125 | return( 0 ); 126 | 127 | case '\\' : 128 | wild++; 129 | default : 130 | if ( sensitive ) { 131 | if ( *wild != *p ) return( 0 ); 132 | } else { 133 | if ( tolower(*wild) != tolower(*p) ) return( 0 ); 134 | } 135 | if ( *wild == '\0' ) { 136 | return( 1 ); 137 | } 138 | wild++, p++; 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /wildcard.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003 Regents of The University of Michigan. 3 | * All Rights Reserved. See COPYRIGHT. 4 | */ 5 | 6 | int wildcard( char *, char *, int ); 7 | --------------------------------------------------------------------------------