diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+## Path IO 1.5.0
+
+* Dropped support for GHC 8.0 and older.
+* Added new functions: `getXdgDirList`, `createFileLink`, `createDirLink`,
+  `removeDirLink`, `getSymlinkTarget`.
+
 ## Path IO 1.4.2
 
 * Fixed various bugs in `listDirRecurRel`, `walkDirRel`, and
diff --git a/LICENSE.md b/LICENSE.md
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -1,4 +1,4 @@
-Copyright © 2016–2018 Mark Karpov
+Copyright © 2016–present Mark Karpov
 
 All rights reserved.
 
diff --git a/Path/IO.hs b/Path/IO.hs
--- a/Path/IO.hs
+++ b/Path/IO.hs
@@ -1,6 +1,6 @@
 -- |
 -- Module      :  Path.IO
--- Copyright   :  © 2016–2019 Mark Karpov
+-- Copyright   :  © 2016–present Mark Karpov
 -- License     :  BSD 3 clause
 --
 -- Maintainer  :  Mark Karpov <markkarpov92@gmail.com>
@@ -12,7 +12,6 @@
 -- scanning and copying of directories, working with temporary
 -- files\/directories, etc.
 
-{-# LANGUAGE CPP               #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE TemplateHaskell   #-}
 {-# LANGUAGE TupleSections     #-}
@@ -47,10 +46,10 @@
   , getAppUserDataDir
   , getUserDocsDir
   , getTempDir
-#if MIN_VERSION_directory(1,2,3)
-  , XdgDirectory (..)
+  , D.XdgDirectory (..)
   , getXdgDir
-#endif
+  , D.XdgDirectoryList (..)
+  , getXdgDirList
     -- * Path transformation
   , AnyPath (..)
   , resolveFile
@@ -66,6 +65,10 @@
   , findFiles
   , findFilesWith
     -- * Symbolic links
+  , createFileLink
+  , createDirLink
+  , removeDirLink
+  , getSymlinkTarget
   , isSymlink
     -- * Temporary files and directories
   , withTempFile
@@ -96,11 +99,9 @@
   , setPermissions
   , copyPermissions
     -- * Timestamps
-#if MIN_VERSION_directory(1,2,3)
   , getAccessTime
   , setAccessTime
   , setModificationTime
-#endif
   , getModificationTime )
 where
 
@@ -124,10 +125,6 @@
 import qualified System.IO.Temp           as T
 import qualified System.PosixCompat.Files as P
 
-#if MIN_VERSION_directory(1,2,3)
-import System.Directory (XdgDirectory)
-#endif
-
 ----------------------------------------------------------------------------
 -- Actions on directories
 
@@ -836,15 +833,14 @@
 getTempDir :: MonadIO m => m (Path Abs Dir)
 getTempDir = liftIO D.getTemporaryDirectory >>= resolveDir'
 
-#if MIN_VERSION_directory(1,2,3)
 -- | Obtain the paths to special directories for storing user-specific
 -- application data, configuration, and cache files, conforming to the
 -- <http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html XDG Base Directory Specification>.
 -- Compared with 'getAppUserDataDir', this function provides a more
 -- fine-grained hierarchy as well as greater flexibility for the user.
 --
--- It also works on Windows, although in that case 'XdgData' and 'XdgConfig'
--- will map to the same directory.
+-- It also works on Windows, although in that case 'D.XdgData' and
+-- 'D.XdgConfig' will map to the same directory.
 --
 -- Note: The directory may not actually exist, in which case you would need
 -- to create it with file mode @700@ (i.e. only accessible by the owner).
@@ -855,15 +851,31 @@
 -- @since 1.2.1
 
 getXdgDir :: MonadIO m
-  => XdgDirectory      -- ^ Which special directory
+  => D.XdgDirectory      -- ^ Which special directory
   -> Maybe (Path Rel Dir)
      -- ^ A relative path that is appended to the path; if 'Nothing', the
      -- base path is returned
   -> m (Path Abs Dir)
 getXdgDir xdgDir suffix =
   liftIO $ (D.getXdgDirectory xdgDir $ maybe "" toFilePath suffix) >>= parseAbsDir
-#endif
 
+-- | Similar to 'getXdgDir' but retrieves the entire list of XDG
+-- directories.
+--
+-- On Windows, 'D.XdgDataDirs' and 'D.XdgConfigDirs' usually map to the same
+-- list of directories unless overridden.
+--
+-- Refer to the docs of 'D.XdgDirectoryList' for more details.
+--
+-- @since 1.5.0
+
+getXdgDirList
+  :: MonadIO m
+  => D.XdgDirectoryList         -- ^ Which special directory list
+  -> m [Path Abs Dir]
+getXdgDirList xdgDirList =
+  liftIO (D.getXdgDirectoryList xdgDirList >>= mapM parseAbsDir)
+
 ----------------------------------------------------------------------------
 -- Path transformation
 
@@ -1158,16 +1170,126 @@
 ----------------------------------------------------------------------------
 -- Symbolic links
 
+-- | Create a /file/ symbolic link. The target path can be either absolute
+-- or relative and need not refer to an existing file. The order of
+-- arguments follows the POSIX convention.
+--
+-- To remove an existing file symbolic link, use 'removeFile'.
+--
+-- Although the distinction between /file/ symbolic links and /directory/
+-- symbolic links does not exist on POSIX systems, on Windows this is an
+-- intrinsic property of every symbolic link and cannot be changed without
+-- recreating the link. A file symbolic link that actually points to a
+-- directory will fail to dereference and vice versa. Moreover, creating
+-- symbolic links on Windows may require privileges unavailable to users
+-- outside the Administrators group. Portable programs that use symbolic
+-- links should take both into consideration.
+--
+-- On Windows, the function is implemented using @CreateSymbolicLink@. Since
+-- 1.3.3.0, the @SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE@ flag is
+-- included if supported by the operating system. On POSIX, the function
+-- uses @symlink@ and is therefore atomic.
+--
+-- Windows-specific errors: This operation may fail with
+-- 'System.IO.Error.permissionErrorType' if the user lacks the privileges to
+-- create symbolic links. It may also fail with
+-- 'System.IO.Error.illegalOperationErrorType' if the file system does not
+-- support symbolic links.
+--
+-- @since 1.5.0
+
+createFileLink
+  :: MonadIO m
+  => Path b0 File               -- ^ Path to the target file
+  -> Path b1 File               -- ^ Path to the link to be created
+  -> m ()
+createFileLink = liftD2 D.createFileLink
+
+-- | Create a /directory/ symbolic link. The target path can be either
+-- absolute or relative and need not refer to an existing directory. The
+-- order of arguments follows the POSIX convention.
+--
+-- To remove an existing directory symbolic link, use 'removeDirLink'.
+--
+-- Although the distinction between /file/ symbolic links and /directory/
+-- symbolic links does not exist on POSIX systems, on Windows this is an
+-- intrinsic property of every symbolic link and cannot be changed without
+-- recreating the link. A file symbolic link that actually points to a
+-- directory will fail to dereference and vice versa. Moreover, creating
+-- symbolic links on Windows may require privileges unavailable to users
+-- outside the Administrators group. Portable programs that use symbolic
+-- links should take both into consideration.
+--
+-- On Windows, the function is implemented using @CreateSymbolicLink@ with
+-- @SYMBOLIC_LINK_FLAG_DIRECTORY@. Since 1.3.3.0, the
+-- @SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE@ flag is also included if
+-- supported by the operating system. On POSIX, this is an alias for
+-- 'createFileLink' and is therefore atomic.
+--
+-- Windows-specific errors: This operation may fail with
+-- 'System.IO.Error.permissionErrorType' if the user lacks the privileges to
+-- create symbolic links. It may also fail with
+-- 'System.IO.Error.illegalOperationErrorType' if the file system does not
+-- support symbolic links.
+--
+-- @since 1.5.0
+
+createDirLink
+  :: MonadIO m
+  => Path b0 Dir                -- ^ Path to the target directory
+  -> Path b1 Dir                -- ^ Path to the link to be created
+  -> m ()
+createDirLink = liftD2 D.createDirectoryLink
+
+-- | Remove an existing /directory/ symbolic link.
+--
+-- On Windows, this is an alias for 'removeDir'. On POSIX systems, this is
+-- an alias for 'removeFile'.
+--
+-- See also: 'removeFile', which can remove an existing /file/ symbolic link.
+--
+-- @since 1.5.0
+
+removeDirLink
+  :: MonadIO m
+  => Path b Dir                 -- ^ Path to the link to be removed
+  -> m ()
+removeDirLink = liftD D.removeDirectoryLink
+
+-- | Retrieve the target path of either a file or directory symbolic link.
+-- The returned path may not exist, and may not even be a valid path.
+--
+-- On Windows systems, this calls @DeviceIoControl@ with
+-- @FSCTL_GET_REPARSE_POINT@. In addition to symbolic links, the function
+-- also works on junction points. On POSIX systems, this calls @readlink@.
+--
+-- Windows-specific errors: This operation may fail with
+-- 'System.IO.Error.illegalOperationErrorType' if the file system does not
+-- support symbolic links.
+--
+-- @since 1.5.0
+
+getSymlinkTarget
+  :: MonadIO m
+  => Path b t                   -- ^ Symlink path
+  -> m FilePath
+getSymlinkTarget = liftD D.getSymbolicLinkTarget
+
+-- | Check whether the path refers to a symbolic link.  An exception is thrown
+-- if the path does not exist or is inaccessible.
+--
+-- On Windows, this checks for @FILE_ATTRIBUTE_REPARSE_POINT@.  In addition to
+-- symbolic links, the function also returns true on junction points.  On
+-- POSIX systems, this checks for @S_IFLNK@.
+--
+-- @since 1.5.0
+
 -- | Check if the given path is a symbolic link.
 --
 -- @since 1.3.0
 
 isSymlink :: MonadIO m => Path b t -> m Bool
-isSymlink p = liftIO (P.isSymbolicLink <$> P.getSymbolicLinkStatus path)
-  where
-    -- NOTE: To be able to correctly check whether it is a symlink or not we
-    -- have to drop the trailing separator from the dir path.
-    path = F.dropTrailingPathSeparator (toFilePath p)
+isSymlink = liftD (D.pathIsSymbolicLink . F.dropTrailingPathSeparator)
 
 ----------------------------------------------------------------------------
 -- Temporary files and directories
@@ -1381,8 +1503,6 @@
 ----------------------------------------------------------------------------
 -- Timestamps
 
-#if MIN_VERSION_directory(1,2,3)
-
 -- | Obtain the time at which the file or directory was last accessed.
 --
 -- The operation may fail with:
@@ -1457,7 +1577,6 @@
 
 setModificationTime :: MonadIO m => Path b t -> UTCTime -> m ()
 setModificationTime = liftD2' D.setModificationTime
-#endif
 
 -- | Obtain the time at which the file or directory was last modified.
 --
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -17,6 +17,6 @@
 
 ## License
 
-Copyright © 2016–2019 Mark Karpov
+Copyright © 2016–present Mark Karpov
 
 Distributed under BSD 3 clause license.
diff --git a/path-io.cabal b/path-io.cabal
--- a/path-io.cabal
+++ b/path-io.cabal
@@ -1,7 +1,7 @@
 name:                 path-io
-version:              1.4.2
+version:              1.5.0
 cabal-version:        1.18
-tested-with:          GHC==7.10.3, GHC==8.0.2, GHC==8.2.2, GHC==8.4.4, GHC==8.6.3
+tested-with:          GHC==8.2.2, GHC==8.4.4, GHC==8.6.5
 license:              BSD3
 license-file:         LICENSE.md
 author:               Mark Karpov <markkarpov92@gmail.com>
@@ -21,9 +21,9 @@
   default:            False
 
 library
-  build-depends:      base         >= 4.8     && < 5.0
+  build-depends:      base         >= 4.10    && < 5.0
                     , containers
-                    , directory    >= 1.2.2   && < 1.4
+                    , directory    >= 1.3.2.0 && < 1.4
                     , dlist        >= 0.8     && < 0.9
                     , exceptions   >= 0.8     && < 0.11
                     , filepath     >= 1.2     && < 1.5
@@ -37,7 +37,7 @@
     ghc-options:      -Wall -Werror
   else
     ghc-options:      -O2 -Wall
- if flag(dev) && impl(ghc >= 8.0)
+  if flag(dev)
     ghc-options:      -Wcompat
                       -Wincomplete-record-updates
                       -Wincomplete-uni-patterns
@@ -53,8 +53,8 @@
     ghc-options:      -Wall -Werror
   else
     ghc-options:      -O2 -Wall
-  build-depends:      base         >= 4.8     && < 5.0
-                    , directory    >= 1.2.2   && < 1.4
+  build-depends:      base         >= 4.10    && < 5.0
+                    , directory    >= 1.3.2.0 && < 1.4
                     , exceptions   >= 0.8     && < 0.11
                     , hspec        >= 2.0     && < 3.0
                     , path         >= 0.6     && < 0.7
diff --git a/tests/Main.hs b/tests/Main.hs
--- a/tests/Main.hs
+++ b/tests/Main.hs
@@ -14,10 +14,6 @@
 import System.PosixCompat.Files
 import Test.Hspec
 
-#if !MIN_VERSION_base(4,8,0)
-import Control.Applicative ((<$>))
-#endif
-
 main :: IO ()
 main = hspec . around withSandbox $ do
 #ifndef mingw32_HOST_OS
@@ -45,12 +41,10 @@
   -- environmental variables HOME and TMPDIR do not exist there.
   describe "getHomeDir"       getHomeDirSpec
   describe "getTempDir"       getTempDirSpec
-#if MIN_VERSION_directory(1,2,3)
   describe "getXdgDir Data"   getXdgDataDirSpec
   describe "getXdgDir Config" getXdgConfigDirSpec
   describe "getXdgDir Cache"  getXdgCacheDirSpec
 #endif
-#endif
 
 listDirSpec :: SpecWith (Path Abs Dir)
 listDirSpec = it "lists directory" $ \dir ->
@@ -198,7 +192,6 @@
       unsetEnv evar
   where evar = "TMPDIR"
 
-#if MIN_VERSION_directory(1,2,3)
 getXdgDataDirSpec :: SpecWith (Path Abs Dir)
 getXdgDataDirSpec =
   it "XDG data dir is influenced by environment variable XDG_DATA_HOME" $ \dir ->
@@ -231,7 +224,6 @@
       unsetEnv evar
   where evar = "XDG_CACHE_HOME"
         name = $(mkRelDir "test")
-#endif
 
 ----------------------------------------------------------------------------
 -- Helpers
