Improve error diagnostics of mmap_full_file().
authorAndre Noll <maan@systemlinux.org>
Thu, 8 Dec 2011 20:01:01 +0000 (21:01 +0100)
committerAndre Noll <maan@systemlinux.org>
Mon, 30 Jan 2012 17:43:36 +0000 (18:43 +0100)
On mmap errors, this function used to return the error code it got
from mmap(). Unfortunately, in at least two cases, this results in
rather obscure error messages:

$ para_afh -i .
main: No such device
$ touch foo; para_afh -i foo
main: Invalid argument

This simple patch specifically checks whether the given fd refers
to a directory or an empty file so that the error messages become
more readable:

$ para_afh -i .
main: failed to mmap "."
main: Is a directory
$ touch foo; para_afh -i foo
main: failed to mmap "foo"
main: file is empty

afh.c
error.h
fd.c

diff --git a/afh.c b/afh.c
index f2745b61b47e67310ce89dd78d9b95944021a7a4..04c13ebdd970831a770bf2b9ab5b178be7c45645 100644 (file)
--- a/afh.c
+++ b/afh.c
@@ -187,8 +187,10 @@ int main(int argc, char **argv)
                int ret2;
                ret = mmap_full_file(conf.inputs[i], O_RDONLY, &audio_file_data,
                        &audio_file_size, &fd);
                int ret2;
                ret = mmap_full_file(conf.inputs[i], O_RDONLY, &audio_file_data,
                        &audio_file_size, &fd);
-               if (ret < 0)
+               if (ret < 0) {
+                       PARA_ERROR_LOG("failed to mmap \"%s\"\n", conf.inputs[i]);
                        goto out;
                        goto out;
+               }
                ret = compute_afhi(conf.inputs[i], audio_file_data, audio_file_size,
                        fd, &afhi);
                if (ret < 0)
                ret = compute_afhi(conf.inputs[i], audio_file_data, audio_file_size,
                        fd, &afhi);
                if (ret < 0)
diff --git a/error.h b/error.h
index 63d4d5db9b6690dacd49505dda27504120309fe7..39c109f9ca5f15670158ad4eb6eb45d19a050898 100644 (file)
--- a/error.h
+++ b/error.h
@@ -441,6 +441,7 @@ extern const char **para_errlist[];
        PARA_ERROR(FGETS, "fgets error"), \
        PARA_ERROR(EOF, "end of file"), \
        PARA_ERROR(READ_PATTERN, "did not read expected pattern"), \
        PARA_ERROR(FGETS, "fgets error"), \
        PARA_ERROR(EOF, "end of file"), \
        PARA_ERROR(READ_PATTERN, "did not read expected pattern"), \
+       PARA_ERROR(EMPTY, "file is empty"), \
 
 
 #define ALSA_WRITE_ERRORS \
 
 
 #define ALSA_WRITE_ERRORS \
diff --git a/fd.c b/fd.c
index 2e05313ea26ece1fd65315e80561fdd626f45fe1..9b6c6917232eb5063bb3acaad51a24ea53226389 100644 (file)
--- a/fd.c
+++ b/fd.c
@@ -541,6 +541,22 @@ int mmap_full_file(const char *path, int open_mode, void **map,
                goto out;
        }
        *size = file_status.st_size;
                goto out;
        }
        *size = file_status.st_size;
+       /*
+        * If the file is empty, *size is zero and mmap() would return EINVAL
+        * (Invalid argument). This error is common enough to spend an extra
+        * error code which explicitly states the problem.
+        */
+       ret = -E_EMPTY;
+       if (*size == 0)
+               goto out;
+       /*
+        * If fd refers to a directory, mmap() returns ENODEV (No such device),
+        * at least on Linux. "Is a directory" seems to be more to the point.
+        */
+       ret = -ERRNO_TO_PARA_ERROR(EISDIR);
+       if (S_ISDIR(file_status.st_mode))
+               goto out;
+
        ret = para_mmap(*size, mmap_prot, mmap_flags, fd, 0, map);
 out:
        if (ret < 0 || !fd_ptr)
        ret = para_mmap(*size, mmap_prot, mmap_flags, fd, 0, map);
 out:
        if (ret < 0 || !fd_ptr)