diff --git a/.gitignore b/.gitignore
new file mode 100644
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+# Vim swap files
+*.sw?
+
+# stack build artifacts
+.stack-work/
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,30 +1,15 @@
-Copyright (c) 2007-2016 Dino Morelli
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above
-      copyright notice, this list of conditions and the following
-      disclaimer in the documentation and/or other materials provided
-      with the distribution.
+Copyright (c) 2007-2016, Dino Morelli <dino@ui3.info>
 
-    * Neither the name of Dino Morelli nor the names of other
-      contributors may be used to endorse or promote products derived
-      from this software without specific prior written permission.
+Permission to use, copy, modify, and/or distribute this software
+for any purpose with or without fee is hereby granted, provided
+that the above copyright notice and this permission notice appear
+in all copies.
 
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
+OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -17,21 +17,20 @@
 
 - Download the cabalized source package [from Hackage](http://hackage.haskell.org/package/photoname)
 - epub-tools is available for Arch Linux [from the AUR](https://aur.archlinux.org/packages/photoname/)
-- Get the source with darcs: `$ darcs get http://hub.darcs.net/dino/photoname`
-- If you're just looking, [browse the source](http://hub.darcs.net/dino/photoname)
+- Get the source with git: `$ git clone https://github.com/dino-/photoname.git`
+- If you're just looking, [browse the source](https://github.com/dino-/photoname)
 
 And once you have it, building the usual way:
 
-    $ cabal configure --enable-tests
-    $ cabal build
-    $ cabal test
-    $ cabal install
+    $ stack build
+    $ stack test
+    $ stack clean
 
 
 ## Installing
 
-Build and install with cabal-install:
-  `$ cabal update ; cabal install photoname`
+Build and install with the included `install.hs` script:
+  `# ./util/install.hs --prefix=/some/dir`
 
 
 ## Contact
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/Setup.lhs b/Setup.lhs
deleted file mode 100644
--- a/Setup.lhs
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/usr/bin/env runhaskell
-
-> import Distribution.Simple
-> import System.Cmd
-
-
-> main = defaultMainWithHooks (simpleUserHooks { runTests = testRunner } )
->     where
->        testRunner _ _ _ _ = do
->           system $ "runhaskell -itestsuite testsuite/runtests.hs"
->           return ()
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,16 @@
+3.3 (2017-12-27)
+
+   * A variety of build-related fixes were made
+
+
+3.2 (2016-10-02)
+
+   * Switched the build from cabal to stack
+   * Added hsinstall installation script
+   * Update copyright year
+   * Various updates to the cabal file
+
+
 3.1 (2015-06-28)
 
    * Removed ambiguous import of `System.Locale.defaultTimeLocale`
diff --git a/photoname.cabal b/photoname.cabal
--- a/photoname.cabal
+++ b/photoname.cabal
@@ -1,8 +1,8 @@
 name:                photoname
 cabal-version:       >= 1.8
-version:             3.2
+version:             3.3
 build-type:          Simple
-license:             BSD3
+license:             ISC
 license-file:        LICENSE
 copyright:           2007-2016 Dino Morelli
 author:              Dino Morelli 
@@ -16,7 +16,16 @@
 category:            Application, Console
 tested-with:         GHC >= 8.0.1
 
-extra-source-files:  testsuite/resources/*.jpg
+extra-source-files:  changelog.md
+                     doc/dev/notes
+                     doc/hcar-photoname.tex
+                     .gitignore
+                     README.md
+                     stack.yaml
+                     testsuite/resources/*.jpg
+                     TODO.md
+                     util/install.hs
+                     util/resources/test.conf
 
 source-repository    head
    type:             darcs
@@ -33,7 +42,8 @@
                      , parsec
                      , time
                      , unix
-   other-modules:    Photoname.Common
+   other-modules:    Paths_photoname
+                     Photoname.Common
                      Photoname.DateFormat
                      Photoname.Date
                      Photoname.Exif
diff --git a/src/photoname.hs b/src/photoname.hs
--- a/src/photoname.hs
+++ b/src/photoname.hs
@@ -3,24 +3,20 @@
 
 {-# LANGUAGE FlexibleContexts #-}
 
-import Control.Monad
+import Control.Monad ( filterM, forM_, unless, when )
+import System.Directory ( createDirectoryIfMissing )
 import System.Environment ( getArgs )
-import System.FilePath
-import System.Posix
-import Text.Printf
+import System.FilePath ( takeDirectory )
+import System.Posix ( createLink, fileExist, getFileStatus,
+   isRegularFile, removeLink )
+import Text.Printf ( printf )
 
-import Photoname.Common
+import Photoname.Common ( Ph, ask, liftIO, runRename, throwError )
 import Photoname.Opts ( Options (..) , parseOpts, usageText )
 import Photoname.DateFormat ( buildDatePath )
 import Photoname.SerialFormat ( buildSerialPath )
 
 
-modeDir :: FileMode
-modeDir = ownerModes       `unionFileModes`
-          groupReadMode    `unionFileModes`
-          groupExecuteMode
-
-
 {- Take a file path to a JPEG file and use EXIF information available to
    link the file at its new location below the given basedir.
 -}
@@ -41,7 +37,7 @@
 
    unless (optNoAction opts) $ do
       -- Make the target dir
-      liftIO $ makeDirectory $ takeDirectory newPath
+      liftIO $ createDirectoryIfMissing True $ takeDirectory newPath
 
       -- Make the new hard link
       liftIO $ createLink oldPath newPath
@@ -51,36 +47,6 @@
          liftIO $ removeLink oldPath
 
       return ()
-
-
-{- Given a list of lists, make a new list where each sublist element 
-   consists of the accumulation of all parts that came before it. 
-   Like this:
-      before: [[1], [2], [3], [4], [5]]
-      after : [[1], [1,2], [1,2,3], [1,2,3,4], [1,2,3,4,5]]
-
-   Many thanks to Betty Diegel for help with this algorithm.
-
-   FIXME Try to rewrite this with a scan or something
--}
-listAcc :: [[a]] -> [[a]]
-listAcc []     = [[]]
-listAcc (x:xs) = listAcc' x xs
-   where
-      listAcc' l (y:ys) = [l] ++ listAcc' (l ++ y) ys
-      listAcc' l []     = [l]
-
-
-{- Ensuring that a directory with subs exists turned out to be a painful 
-   process involving making each parent dir piece by piece but not trying
-   to make anything that's already there.
--}
-makeDirectory :: FilePath -> IO ()
-makeDirectory d =
-   let makeOneDir dir = do
-         exists <- fileExist dir
-         unless exists $ createDirectory dir modeDir
-   in  mapM_ makeOneDir $ listAcc $ splitPath d
 
 
 -- Figure out and execute what the user wants based on the supplied args.
diff --git a/stack.yaml b/stack.yaml
--- a/stack.yaml
+++ b/stack.yaml
@@ -1,71 +1,7 @@
-# This file was automatically generated by 'stack init'
-#
-# Some commonly used options have been documented as comments in this file.
-# For advanced use and comprehensive documentation of the format, please see:
-# http://docs.haskellstack.org/en/stable/yaml_configuration/
-
-# Resolver to choose a 'specific' stackage snapshot or a compiler version.
-# A snapshot resolver dictates the compiler version and the set of packages
-# to be used for project dependencies. For example:
-#
-# resolver: lts-3.5
-# resolver: nightly-2015-09-21
-# resolver: ghc-7.10.2
-# resolver: ghcjs-0.1.0_ghc-7.10.2
-# resolver:
-#  name: custom-snapshot
-#  location: "./custom-snapshot.yaml"
-resolver: lts-7.2
+resolver: lts-10.1
 
-# User packages to be built.
-# Various formats can be used as shown in the example below.
-#
-# packages:
-# - some-directory
-# - https://example.com/foo/bar/baz-0.0.2.tar.gz
-# - location:
-#    git: https://github.com/commercialhaskell/stack.git
-#    commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a
-# - location: https://github.com/commercialhaskell/stack/commit/e7b331f14bcffb8367cd58fbfc8b40ec7642100a
-#   extra-dep: true
-#  subdirs:
-#  - auto-update
-#  - wai
-#
-# A package marked 'extra-dep: true' will only be built if demanded by a
-# non-dependency (i.e. a user package), and its test suites and benchmarks
-# will not be run. This is useful for tweaking upstream packages.
-#packages: []
 packages:
 - .
-- https://hackage.haskell.org/package/exif-3000.0.0/exif-3000.0.0.tar.gz
 
-# Dependency packages to be pulled from upstream that are not in the resolver
-# (e.g., acme-missiles-0.3)
-#extra-deps: []
 extra-deps:
 - exif-3000.0.0
-
-# Override default flag values for local packages and extra-deps
-flags: {}
-
-# Extra package databases containing global packages
-extra-package-dbs: []
-
-# Control whether we use the GHC we find on the path
-# system-ghc: true
-#
-# Require a specific version of stack, using version ranges
-# require-stack-version: -any # Default
-# require-stack-version: ">=1.2"
-#
-# Override the architecture used by stack, especially useful on Windows
-# arch: i386
-# arch: x86_64
-#
-# Extra directories used by stack for building
-# extra-include-dirs: [/path/to/dir]
-# extra-lib-dirs: [/path/to/dir]
-#
-# Allow a newer minor version of GHC than the snapshot specifies
-# compiler-check: newer-minor
diff --git a/util/install.hs b/util/install.hs
--- a/util/install.hs
+++ b/util/install.hs
@@ -6,7 +6,6 @@
 import Control.Exception
 import Control.Monad
 import Data.List
-import Data.Version
 import Distribution.Package
 import Distribution.PackageDescription hiding ( error, options )
 import Distribution.PackageDescription.Parse
@@ -54,7 +53,7 @@
    -- then pass a pile of what we know to a function to create the
    -- installation dirs
    dirs <- constructDirs opts . package . packageDescription
-      <$> readPackageDescription normal (head cabalFiles)
+      <$> readGenericPackageDescription normal (head cabalFiles)
 
 
    -- Perform the installation
diff --git a/util/prefs/boring b/util/prefs/boring
deleted file mode 100644
--- a/util/prefs/boring
+++ /dev/null
@@ -1,124 +0,0 @@
-# This file contains a list of extended regular expressions, one per
-# line. A file path matching any of these expressions will be filtered
-# out during `darcs add', or when the `--look-for-adds' flag is passed
-# to `darcs whatsnew' and `record'. The entries in ~/.darcs/boring (if
-# it exists) supplement those in this file.
-# 
-# Blank lines, and lines beginning with an octothorpe (#) are ignored.
-# See regex(7) for a description of extended regular expressions.
-
-### compiler and interpreter intermediate files
-# haskell (ghc) interfaces
-\.hi$
-\.hi-boot$
-\.o-boot$
-# object files
-\.o$
-\.o\.cmd$
-# profiling haskell
-\.p_hi$
-\.p_o$
-# haskell program coverage resp. profiling info
-\.tix$
-\.prof$
-# fortran module files
-\.mod$
-# linux kernel
-\.ko\.cmd$
-\.mod\.c$
-(^|/)\.tmp_versions($|/)
-# *.ko files aren't boring by default because they might
-# be Korean translations rather than kernel modules
-# \.ko$
-# python, emacs, java byte code
-\.py[co]$
-\.elc$
-\.class$
-# objects and libraries; lo and la are libtool things
-\.(obj|a|exe|so|lo|la)$
-# compiled zsh configuration files
-\.zwc$
-# Common LISP output files for CLISP and CMUCL
-\.(fas|fasl|sparcf|x86f)$
-
-### build and packaging systems
-# cabal intermediates
-\.installed-pkg-config
-\.setup-config
-# standard cabal build dir, might not be boring for everybody
-# ^dist(/|$)
-# autotools
-(^|/)autom4te\.cache($|/)
-(^|/)config\.(log|status)$
-# microsoft web expression, visual studio metadata directories
-\_vti_cnf$
-\_vti_pvt$
-# gentoo tools
-\.revdep-rebuild.*
-# generated dependencies
-^\.depend$
-
-### version control systems
-# cvs
-(^|/)CVS($|/)
-\.cvsignore$
-# cvs, emacs locks
-^\.#
-# rcs
-(^|/)RCS($|/)
-,v$
-# subversion
-(^|/)\.svn($|/)
-# mercurial
-(^|/)\.hg($|/)
-# git
-(^|/)\.git($|/)
-# bzr
-\.bzr$
-# sccs
-(^|/)SCCS($|/)
-# darcs
-(^|/)_darcs($|/)
-(^|/)\.darcsrepo($|/)
-^\.darcs-temp-mail$
--darcs-backup[[:digit:]]+$
-# gnu arch
-(^|/)(\+|,)
-(^|/)vssver\.scc$
-\.swp$
-(^|/)MT($|/)
-(^|/)\{arch\}($|/)
-(^|/).arch-ids($|/)
-# bitkeeper
-(^|/)BitKeeper($|/)
-(^|/)ChangeSet($|/)
-
-### miscellaneous
-# backup files
-~$
-\.bak$
-\.BAK$
-# patch originals and rejects
-\.orig$
-\.rej$
-# X server
-\..serverauth.*
-# image spam
-\#
-(^|/)Thumbs\.db$
-# vi, emacs tags
-(^|/)(tags|TAGS)$
-#(^|/)\.[^/]
-# core dumps
-(^|/|\.)core$
-# partial broken files (KIO copy operations)
-\.part$
-# waf files, see http://code.google.com/p/waf/
-(^|/)\.waf-[[:digit:].]+-[[:digit:]]+($|/)
-(^|/)\.lock-wscript$
-# mac os finder
-(^|/)\.DS_Store$
-# emacs saved sessions (desktops)
-(^|.*/)\.emacs\.desktop(\.lock)?$
-
-(^|/).stack-work($|/)
