1

I'm trying to run the Piwigo image gallery/DAM on a Raspberry Pi via Arch Linux ARM with Apache 2.4 and PHP7. Piwigo is running happily. For a chain of reasons outside the scope of this question, my goal is to leave the tens of thousands of image files on a Windows machine, share them up through CIFS and symlink them into Piwigo's FTP/synchronization directory. Symlinking files into Piwigo is an everyday practice, recommended by its documentation and developers in its forums.

My files are mounted with options making them owned by Apache's user. All files, including symlinks into the CIFS share, are served OK by Apache if their URLs are typed in. This isn't a permissions issue, or at least not a simple one. The problem is that symlinks into the CIFS share are not listed or synchronized by Piwigo's PHP. Symlinks to the local filesystem are synchronized OK. Although autoindexes aren't involved in my goal, I think it's a clue that the same exact rules apply to indexes generated by mod_autoindex.

Setting up a test case:

[alarm@alarmpi familytreetest]$ sudo -u http -s
[http@alarmpi ~]$ mkdir /mnt/localfam
[http@alarmpi ~]$ cp /mnt/familytreetest/Bulk\ Uploads/1977\ Andrews/1977\ Andrews_1.jpg /mnt/localfam/
[http@alarmpi ~]$ ln -s /mnt/familytreetest/Bulk\ Uploads/1977\ Andrews/1977\ Andrews_1.jpg /srv/http/piwigo/galleries/family/CIFSlink.jpg
[http@alarmpi ~]$ ln -s /mnt/localfam/ /srv/http/piwigo/galleries/family/Locallink.jpg 
[http@alarmpi ~]$ cp /mnt/localfam/1977\ Andrews_1.jpg piwigo/galleries/family/1977_Andrews_1.jpg  

The name change in copying the file into Piwigo is intentional; Piwigo can't handle spaces in this particular function.

When I was recording and editing all this output, I failed to think about paths with spaces. I just tested; symlinks to paths on the local filesystem which include spaces are both synchronized by Piwigo and listed by mod_autoindex. I'd prefer not to spend more hours redoing all the listings to convince people on this one matter, but will if necessary.

[http@alarmpi ~]$ ls -l piwigo/galleries/family/
total 240
-rwxr-xr-x 1 http http 237934 Dec 23 17:43 1977_Andrews_1.jpg
lrwxrwxrwx 1 http http     64 Dec 23 17:28 CIFSlink.jpg -> /mnt/familytreetest/Bulk Uploads/1977 Andrews/1977 Andrews_1.jpg
lrwxrwxrwx 1 http http     32 Dec 23 17:42 Locallink.jpg -> /mnt/localfam/1977 Andrews_1.jpg

At this point I run Piwigo's synchronization tool. I get two images added to my database. CIFSlink.jpg is left out. If I now type in any of these files' URLs in any browser on any machine on my network, I get the picture on screen OK.

[http@alarmpi ~]$ curl -I 192.168.0.100/piwigo/galleries/family/CIFSlink.jpg
HTTP/1.1 200 OK
Date: Sat, 23 Dec 2017 23:35:49 GMT
Server: Apache/2.4.25 (Unix) PHP/7.1.5
Last-Modified: Mon, 24 Jul 2017 18:00:52 GMT
ETag: "3a16e-55513feda1d00"
Accept-Ranges: bytes
Content-Length: 237934
Content-Type: image/jpeg

I copy the sync directory out to Apache's DocumentRoot (which is also user http's home directory) so I can browse to it with mod_autoindex.

[http@alarmpi ~]$ cp -r piwigo/galleries/family/ /srv/http/

Here too CIFSlink.jpg is left out of the listing.

[http@alarmpi ~]$ curl 192.168.0.100/family/
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
 <head>
  <title>Index of /family</title>
 </head>
 <body>
<h1>Index of /family</h1>
  <table>
   <tr><th valign="top"><img src="/icons/blank.gif" alt="[ICO]"></th><th><a href="?C=N;O=D">Name</a></th><th><a href="?C=M;O=A">Last modified</a></th><th><a href="?C=S;O=A">Size</a></th><th><a href="?C=D;O=A">Description</a></th></tr>
   <tr><th colspan="5"><hr></th></tr>
<tr><td valign="top"><img src="/icons/back.gif" alt="[PARENTDIR]"></td><td><a href="/">Parent Directory</a>       </td><td>&nbsp;</td><td align="right">  - </td><td>&nbsp;</td></tr>
<tr><td valign="top"><img src="/icons/image2.gif" alt="[IMG]"></td><td><a href="1977_Andrews_1.jpg">1977_Andrews_1.jpg</a>     </td><td align="right">2017-12-23 18:49  </td><td align="right">232K</td><td>&nbsp;</td></tr>
<tr><td valign="top"><img src="/icons/image2.gif" alt="[IMG]"></td><td><a href="Locallink.jpg">Locallink.jpg</a>          </td><td align="right">2017-12-23 17:22  </td><td align="right">232K</td><td>&nbsp;</td></tr>
   <tr><th colspan="5"><hr></th></tr>
</table>
</body></html>

Here too, the file is accessible just fine by Apache through its URL.

[http@alarmpi ~]$ curl -I 192.168.0.100/family/CIFSlink.jpg
HTTP/1.1 200 OK
Date: Sat, 23 Dec 2017 23:58:29 GMT
Server: Apache/2.4.25 (Unix) PHP/7.1.5
Last-Modified: Mon, 24 Jul 2017 18:00:52 GMT
ETag: "3a16e-55513feda1d00"
Accept-Ranges: bytes
Content-Length: 237934
Content-Type: image/jpeg

Apache's access and error logs removed to get under 30K chars. Didn't show anything seeming relevant.

EDIT: If I mount the CIFS share directly to where I'm putting the symlinks, files are not seen by the PHP application, even if they have no illegal characters, but are included in indexes from mod_autoindex.

My httpd.conf, passed through awk to strip comments and blank lines:

[alarm@alarmpi familytreetest]$ sudo awk '!/^ *#/ && NF' /etc/httpd/conf/httpd.conf
ServerRoot "/etc/httpd"
Listen 80
LoadModule authn_file_module modules/mod_authn_file.so
LoadModule authn_core_module modules/mod_authn_core.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
LoadModule authz_user_module modules/mod_authz_user.so
LoadModule authz_core_module modules/mod_authz_core.so
LoadModule access_compat_module modules/mod_access_compat.so
LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule reqtimeout_module modules/mod_reqtimeout.so
LoadModule include_module modules/mod_include.so
LoadModule filter_module modules/mod_filter.so
LoadModule mime_module modules/mod_mime.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule env_module modules/mod_env.so
LoadModule headers_module modules/mod_headers.so
LoadModule unique_id_module modules/mod_unique_id.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule version_module modules/mod_version.so
LoadModule slotmem_shm_module modules/mod_slotmem_shm.so
LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
LoadModule unixd_module modules/mod_unixd.so
LoadModule status_module modules/mod_status.so
LoadModule autoindex_module modules/mod_autoindex.so
<IfModule !mpm_prefork_module>
        #LoadModule cgid_module modules/mod_cgid.so
</IfModule>
<IfModule mpm_prefork_module>
        #LoadModule cgi_module modules/mod_cgi.so
</IfModule>
LoadModule negotiation_module modules/mod_negotiation.so
LoadModule dir_module modules/mod_dir.so
LoadModule userdir_module modules/mod_userdir.so
LoadModule alias_module modules/mod_alias.so
LoadModule php7_module modules/libphp7.so
<FilesMatch \.php$>
        SetHandler application/x-httpd-php
</FilesMatch>
<IfModule unixd_module>
User http
Group http
</IfModule>
ServerAdmin you@example.com
<Directory />
    AllowOverride none
    Require all denied
</Directory>
DocumentRoot "/srv/http"
<Directory "/srv/http">
    Options +Indexes +FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>
<IfModule dir_module>
    DirectoryIndex index.html
</IfModule>
<Files ".ht*">
    Require all denied
</Files>
ErrorLog "/var/log/httpd/error_log"
LogLevel warn
<IfModule log_config_module>
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
        LogFormat "%h %l %u %t \"%r\" %>s %b" common
    <IfModule logio_module>
      LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
    </IfModule>
    CustomLog "/var/log/httpd/access_log" common
</IfModule>
<IfModule alias_module>
    ScriptAlias /cgi-bin/ "/srv/http/cgi-bin/"
</IfModule>
<IfModule cgid_module>
</IfModule>
<Directory "/srv/http/cgi-bin">
    AllowOverride None
    Options None
    Require all granted
</Directory>
<IfModule headers_module>
    RequestHeader unset Proxy early
</IfModule>
<IfModule mime_module>
    TypesConfig conf/mime.types
    AddType application/x-compress .Z
    AddType application/x-gzip .gz .tgz
</IfModule>
Include conf/extra/httpd-mpm.conf
Include conf/extra/httpd-multilang-errordoc.conf
Include conf/extra/httpd-autoindex.conf
Include conf/extra/httpd-languages.conf
Include conf/extra/httpd-userdir.conf
Include conf/extra/httpd-default.conf
Include conf/extra/phpmyadmin.conf
<IfModule proxy_html_module>
Include conf/extra/proxy-html.conf
</IfModule>
Include conf/extra/php7_module.conf
<IfModule ssl_module>
SSLRandomSeed startup builtin
SSLRandomSeed connect builtin
</IfModule>

I haven't changed httpd.conf in two weeks and have restarted it a dozen times to be sure the server's up to date on its configuration.

I had my other Apache conf files, but they put me over 30K characters. Available upon request by editing other stuff out.

SELinux isn't officially supported on Arch Linux, let alone ALARM. I have not gone through the super-hairy process to install the half-working version you can put in. In any case, its main diagnostic command says it's not here and can't be screwing stuff up.

[alarm@alarmpi ~]$ sestatus
-bash: sestatus: command not found

The final thing I can think of is to throw you an strace of Apache trying to scan these files. First, Piwigo's worker doing a synchronization. Actual mention of the files it's supposed to see at lines 57-61 and again at 81-84. I notice that in the first block it scans the first two files, then hits the directory again, and only then hits CIFSlink. In the second block, it's potentially interesting that CIFSlink and only CIFSlink is hit twice. Everything's still return status 0, though. I've gone back and confirmed that the final action on files at 158-166 happens even when I perform no action but a synchronization before Ctrl+C terminating Apache. That sole call of readlink() at 162 remains the only call even if two local symlinks are successfully synchronized.

[alarm@alarmpi ~]$ nl phpstrace.txt | less
(snip)
    43  20559 send(10, "E\0\0\0\3\nSELECT IF(MAX(id)+1 IS NUL"..., 73, MSG_DONTWAIT) = 73
    44  20559 poll([{fd=10, events=POLLIN|POLLERR|POLLHUP}], 1, 1471228928) = 1 ([{fd=10, revents=POLLIN}])
    45  20559 recv(10, "\1\0\0\1\0019\0\0\2\3def\0\0\0#IF(MAX(id)+1 IS"..., 1479, MSG_DONTWAIT) = 90
    46  20559 gettimeofday({tv_sec=1514078472, tv_usec=648129}, NULL) = 0
    47  20559 stat64("./galleries", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    48  20559 open("./galleries", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = 11
    49  20559 fstat64(11, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    50  20559 getdents(11, /* 4 entries */, 32768) = 76
    51  20559 stat64("./galleries/.", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    52  20559 stat64("./galleries/..", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    53  20559 stat64("./galleries/family", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    54  20559 open("./galleries/family", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = 12
    55  20559 fstat64(12, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    56  20559 getdents(12, /* 5 entries */, 32768) = 116
    57  20559 stat64("./galleries/family/1977_Andrews_1.jpg", {st_mode=S_IFREG|0755, st_size=237934, ...}) = 0
    58  20559 stat64("./galleries/family/Locallink.jpg", {st_mode=S_IFREG|0755, st_size=237934, ...}) = 0
    59  20559 stat64("./galleries/family/.", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    60  20559 stat64("./galleries/family/CIFSlink.jpg", {st_mode=S_IFREG|0755, st_size=237934, ...}) = 0
    61  20559 stat64("./galleries/family/..", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    62  20559 getdents(12, /* 0 entries */, 32768) = 0
    63  20559 close(12)                         = 0
    64  20559 stat64("./galleries/index.php", {st_mode=S_IFREG|0644, st_size=1765, ...}) = 0
    65  20559 getdents(11, /* 0 entries */, 32768) = 0
    66  20559 close(11)                         = 0
    67  20559 gettimeofday({tv_sec=1514078472, tv_usec=671461}, NULL) = 0
    68  20559 gettimeofday({tv_sec=1514078472, tv_usec=672515}, NULL) = 0
    69  20559 stat64("./galleries", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    70  20559 open("./galleries", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = 11
    71  20559 fstat64(11, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    72  20559 getdents(11, /* 4 entries */, 32768) = 76
    73  20559 stat64("./galleries/family", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    74  20559 stat64("./galleries/index.php", {st_mode=S_IFREG|0644, st_size=1765, ...}) = 0
    75  20559 getdents(11, /* 0 entries */, 32768) = 0
    76  20559 close(11)                         = 0
    77  20559 stat64("./galleries/family", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    78  20559 open("./galleries/family", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = 11
    79  20559 fstat64(11, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    80  20559 getdents(11, /* 5 entries */, 32768) = 116
    81  20559 stat64("./galleries/family/1977_Andrews_1.jpg", {st_mode=S_IFREG|0755, st_size=237934, ...}) = 0
    82  20559 stat64("./galleries/family/Locallink.jpg", {st_mode=S_IFREG|0755, st_size=237934, ...}) = 0
    83  20559 stat64("./galleries/family/CIFSlink.jpg", {st_mode=S_IFREG|0755, st_size=237934, ...}) = 0
    84  20559 stat64("./galleries/family/CIFSlink.jpg", {st_mode=S_IFREG|0755, st_size=237934, ...}) = 0
    85  20559 getdents(11, /* 0 entries */, 32768) = 0
    86  20559 close(11)                         = 0
    87  20559 gettimeofday({tv_sec=1514078472, tv_usec=685288}, NULL) = 0
    88  20559 gettimeofday({tv_sec=1514078472, tv_usec=686100}, NULL) = 0
    89  20559 send(10, "I\0\0\0\3\nSELECT id, path\n  FROM piw"..., 77, MSG_DONTWAIT) = 77
    90  20559 poll([{fd=10, events=POLLIN|POLLERR|POLLHUP}], 1, 1471228928) = 1 ([{fd=10, revents=POLLIN}])
    91  20559 recv(10, "\1\0\0\1\2=\0\0\2\3def\tpiwigopix\rpiwigo_i"..., 1389, MSG_DONTWAIT) = 240
    92  20559 gettimeofday({tv_sec=1514078472, tv_usec=691698}, NULL) = 0
    93  20559 gettimeofday({tv_sec=1514078472, tv_usec=692510}, NULL) = 0
    94  20559 send(10, "A\0\0\0\3\nSELECT IF(MAX(id)+1 IS NUL"..., 69, MSG_DONTWAIT) = 69
    95  20559 poll([{fd=10, events=POLLIN|POLLERR|POLLHUP}], 1, 1471228928) = 1 ([{fd=10, revents=POLLIN}])
    96  20559 recv(10, "\1\0\0\1\0019\0\0\2\3def\0\0\0#IF(MAX(id)+1 IS"..., 1149, MSG_DONTWAIT) = 90
    97  20559 gettimeofday({tv_sec=1514078472, tv_usec=697001}, NULL) = 0
    98  20559 gettimeofday({tv_sec=1514078472, tv_usec=697784}, NULL) = 0
    99  20559 gettimeofday({tv_sec=1514078472, tv_usec=698459}, NULL) = 0
   100  20559 gettimeofday({tv_sec=1514078472, tv_usec=699212}, NULL) = 0
   101  20559 gettimeofday({tv_sec=1514078472, tv_usec=699768}, NULL) = 0
   102  20559 send(10, "\314\0\0\0\3\nSELECT DISTINCT c.id\n  FRO"..., 208, MSG_DONTWAIT) = 208
   103  20559 poll([{fd=10, events=POLLIN|POLLERR|POLLHUP}], 1, 1471228928) = 1 ([{fd=10, revents=POLLIN}])
   104  20559 recv(10, "\1\0\0\1\0015\0\0\2\3def\tpiwigopix\1c\21piwigo"..., 1059, MSG_DONTWAIT) = 80
   105  20559 gettimeofday({tv_sec=1514078472, tv_usec=706517}, NULL) = 0
   106  20559 gettimeofday({tv_sec=1514078472, tv_usec=707219}, NULL) = 0
   107  20559 send(10, "\236\0\0\0\3\nSELECT DISTINCT id\n  FROM "..., 162, MSG_DONTWAIT) = 162
   108  20559 poll([{fd=10, events=POLLIN|POLLERR|POLLHUP}], 1, 1471228928) = 1 ([{fd=10, revents=POLLIN}])
   109  20559 recv(10, "\1\0\0\1\1E\0\0\2\3def\tpiwigopix\21piwigo_c"..., 979, MSG_DONTWAIT) = 96
   110  20559 gettimeofday({tv_sec=1514078472, tv_usec=713776}, NULL) = 0
   111  20559 gettimeofday({tv_sec=1514078472, tv_usec=714489}, NULL) = 0
   112  20559 gettimeofday({tv_sec=1514078472, tv_usec=715212}, NULL) = 0
   113  20559 gettimeofday({tv_sec=1514078472, tv_usec=715798}, NULL) = 0
   114  20559 send(10, "p\0\0\0\3\nSELECT id, id_uppercat, up"..., 116, MSG_DONTWAIT) = 116
   115  20559 poll([{fd=10, events=POLLIN|POLLERR|POLLHUP}], 1, 1471228928) = 1 ([{fd=10, revents=POLLIN}])
   116  20559 recv(10, "\1\0\0\1\5E\0\0\2\3def\tpiwigopix\21piwigo_c"..., 883, MSG_DONTWAIT) = 468
   117  20559 gettimeofday({tv_sec=1514078472, tv_usec=721655}, NULL) = 0
   118  20559 gettimeofday({tv_sec=1514078472, tv_usec=723454}, NULL) = 0
   119  20559 gettimeofday({tv_sec=1514078472, tv_usec=724212}, NULL) = 0
   120  20559 gettimeofday({tv_sec=1514078472, tv_usec=724792}, NULL) = 0
   121  20559 send(10, "R\0\0\0\3\nSELECT id\n  FROM piwigo_ca"..., 86, MSG_DONTWAIT) = 86
   122  20559 poll([{fd=10, events=POLLIN|POLLERR|POLLHUP}], 1, 1471228928) = 1 ([{fd=10, revents=POLLIN}])
   123  20559 recv(10, "\1\0\0\1\1E\0\0\2\3def\tpiwigopix\21piwigo_c"..., 415, MSG_DONTWAIT) = 102
   124  20559 gettimeofday({tv_sec=1514078472, tv_usec=730105}, NULL) = 0
   125  20559 gettimeofday({tv_sec=1514078472, tv_usec=730977}, NULL) = 0
   126  20559 send(10, "_\0\0\0\3\nSELECT id, path, represent"..., 99, MSG_DONTWAIT) = 99
   127  20559 poll([{fd=10, events=POLLIN|POLLERR|POLLHUP}], 1, 1471228928) = 1 ([{fd=10, revents=POLLIN}])
   128  20559 recv(10, "\1\0\0\1\3=\0\0\2\3def\tpiwigopix\rpiwigo_i"..., 313, MSG_DONTWAIT) = 313
   129  20559 poll([{fd=10, events=POLLIN|POLLERR|POLLHUP}], 1, 1471228928) = 1 ([{fd=10, revents=POLLIN}])
   130  20559 recv(10, "77_Andrews_1.jpg\373\5\0\0\10\376\0\0\2\0", 2500, MSG_DONTWAIT) = 26
   131  20559 gettimeofday({tv_sec=1514078472, tv_usec=737467}, NULL) = 0
   132  20559 gettimeofday({tv_sec=1514078472, tv_usec=738418}, NULL) = 0
   133  20559 gettimeofday({tv_sec=1514078472, tv_usec=739147}, NULL) = 0
   134  20559 gettimeofday({tv_sec=1514078472, tv_usec=740066}, NULL) = 0
   135  20559 send(10, "G\0\0\0\3\nUPDATE piwigo_images\n  SET"..., 75, MSG_DONTWAIT) = 75
   136  20559 poll([{fd=10, events=POLLIN|POLLERR|POLLHUP}], 1, 1471228928) = 1 ([{fd=10, revents=POLLIN}])
   137  20559 recv(10, "0\0\0\1\0\0\0\2\0\0\0(Rows matched: 1  Cha"..., 2474, MSG_DONTWAIT) = 52
   138  20559 gettimeofday({tv_sec=1514078472, tv_usec=745234}, NULL) = 0
   139  20559 gettimeofday({tv_sec=1514078472, tv_usec=746016}, NULL) = 0
   140  20559 send(10, "G\0\0\0\3\nUPDATE piwigo_images\n  SET"..., 75, MSG_DONTWAIT) = 75
   141  20559 poll([{fd=10, events=POLLIN|POLLERR|POLLHUP}], 1, 1471228928) = 1 ([{fd=10, revents=POLLIN}])
   142  20559 recv(10, "0\0\0\1\0\0\0\2\0\0\0(Rows matched: 1  Cha"..., 2422, MSG_DONTWAIT) = 52
   143  20559 gettimeofday({tv_sec=1514078472, tv_usec=750938}, NULL) = 0
   144  20559 gettimeofday({tv_sec=1514078472, tv_usec=751526}, NULL) = 0
   145  20559 gettimeofday({tv_sec=1514078472, tv_usec=752395}, NULL) = 0
   146  20559 gettimeofday({tv_sec=1514078472, tv_usec=752957}, NULL) = 0
   147  20559 send(10, "R\0\0\0\3\nSELECT id\n  FROM piwigo_ca"..., 86, MSG_DONTWAIT) = 86
   148  20559 poll([{fd=10, events=POLLIN|POLLERR|POLLHUP}], 1, 1471228928) = 1 ([{fd=10, revents=POLLIN}])
   149  20559 recv(10, "\1\0\0\1\1E\0\0\2\3def\tpiwigopix\21piwigo_c"..., 2370, MSG_DONTWAIT) = 102
   150  20559 gettimeofday({tv_sec=1514078472, tv_usec=758239}, NULL) = 0
   151  20559 gettimeofday({tv_sec=1514078472, tv_usec=758945}, NULL) = 0
   152  20559 send(10, "\205\0\0\0\3\nSELECT id, path, represent"..., 137, MSG_DONTWAIT) = 137
   153  20559 poll([{fd=10, events=POLLIN|POLLERR|POLLHUP}], 1, 1471228928) = 1 ([{fd=10, revents=POLLIN}])
   154  20559 recv(10, "\1\0\0\1\3=\0\0\2\3def\tpiwigopix\rpiwigo_i"..., 2268, MSG_DONTWAIT) = 339
   155  20559 gettimeofday({tv_sec=1514078472, tv_usec=764752}, NULL) = 0
   156  20559 gettimeofday({tv_sec=1514078472, tv_usec=765603}, NULL) = 0
   157  20559 gettimeofday({tv_sec=1514078472, tv_usec=766339}, NULL) = 0
   158  20559 stat64("././galleries/family/Locallink.jpg", {st_mode=S_IFREG|0755, st_size=237934, ...}) = 0
   159  20559 getcwd("/srv/http/piwigo", 4096)  = 17
   160  20559 gettimeofday({tv_sec=1514078472, tv_usec=768178}, NULL) = 0
   161  20559 lstat64("/srv/http/piwigo/././galleries/family/Locallink.jpg", {st_mode=S_IFLNK|0777, st_size=32, ...}) = 0
   162  20559 readlink("/srv/http/piwigo/././galleries/family/Locallink.jpg", "/mnt/localfam/1977 Andrews_1.jpg", 4096) = 32
   163  20559 lstat64("/mnt/localfam/1977 Andrews_1.jpg", {st_mode=S_IFREG|0755, st_size=237934, ...}) = 0
   164  20559 lstat64("/mnt/localfam", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
   165  20559 lstat64("/mnt", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
   166  20559 open("/mnt/localfam/1977 Andrews_1.jpg", O_RDONLY) = 11
   167  20559 fstat64(11, {st_mode=S_IFREG|0755, st_size=237934, ...}) = 0
   168  20559 _llseek(11, 0, [0], SEEK_CUR)     = 0
   169  20559 read(11, "\377\330\377\340\0\20JFIF\0\1\1\0\0\1\0\1\0\0\377\333\0C\0\r\t\n\v\n\10\r"..., 8192) = 8192
   170  20559 close(11)                         = 0

And finally, the strace of mod_autoindex indexing a directory without including CIFSlink. File scanning at 43-48. Once again the successful files get scanned, then the single dot, then CIFSlink but once again it seems to get scanned in the end.

[alarm@alarmpi ~]$ nl indexstrace.txt | less
     1  20536 _newselect(0, NULL, NULL, NULL, {tv_sec=1, tv_usec=0}) = 0 (Timeout)
     2  20536 wait4(-1, 0x7ecec9f0, WNOHANG|WSTOPPED, NULL) = 0
     3  20536 _newselect(0, NULL, NULL, NULL, {tv_sec=1, tv_usec=0} <unfinished ...>
     4  20558 <... accept4 resumed> {sa_family=AF_INET6, sin6_port=htons(10914), inet_pton(AF_INET6, "::ffff:192.168.0.107", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=0}, [128->28], SOCK_CLOEXEC) = 9
     5  20558 getsockname(9, {sa_family=AF_INET6, sin6_port=htons(80), inet_pton(AF_INET6, "::ffff:192.168.0.100", &sin6_addr), sin6_flowinfo=htonl(0), sin6_scope_id=0}, [128->28]) = 0
     6  20558 fcntl64(9, F_GETFL)               = 0x2 (flags O_RDWR)
     7  20558 fcntl64(9, F_SETFL, O_RDWR|O_NONBLOCK) = 0
     8  20558 gettimeofday({tv_sec=1514078503, tv_usec=263541}, NULL) = 0
     9  20558 read(9, "GET /family/ HTTP/1.1\r\nHost: 192"..., 8000) = 287
    10  20558 gettimeofday({tv_sec=1514078503, tv_usec=264926}, NULL) = 0
    11  20558 gettimeofday({tv_sec=1514078503, tv_usec=265863}, NULL) = 0
    12  20558 gettimeofday({tv_sec=1514078503, tv_usec=266380}, NULL) = 0
    13  20558 gettimeofday({tv_sec=1514078503, tv_usec=266905}, NULL) = 0
    14  20558 gettimeofday({tv_sec=1514078503, tv_usec=267410}, NULL) = 0
    15  20558 gettimeofday({tv_sec=1514078503, tv_usec=267897}, NULL) = 0
    16  20558 gettimeofday({tv_sec=1514078503, tv_usec=268395}, NULL) = 0
    17  20558 gettimeofday({tv_sec=1514078503, tv_usec=268985}, NULL) = 0
    18  20558 gettimeofday({tv_sec=1514078503, tv_usec=269744}, NULL) = 0
    19  20558 stat64("/srv/http/family/", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    20  20558 stat64("/srv/http/family/index.html", 0x7ecec600) = -1 ENOENT (No such file or directory)
    21  20558 lstat64("/srv", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    22  20558 lstat64("/srv/http", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    23  20558 lstat64("/srv/http/family", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    24  20558 lstat64("/srv/http/family/index.html", 0x7ecec600) = -1 ENOENT (No such file or directory)
    25  20558 stat64("/srv/http/family/index.php", 0x7ecec600) = -1 ENOENT (No such file or directory)
    26  20558 lstat64("/srv", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    27  20558 lstat64("/srv/http", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    28  20558 lstat64("/srv/http/family", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    29  20558 lstat64("/srv/http/family/index.php", 0x7ecec600) = -1 ENOENT (No such file or directory)
    30  20558 stat64("/srv/http/family/index.html", 0x7ecec600) = -1 ENOENT (No such file or directory)
    31  20558 lstat64("/srv", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    32  20558 lstat64("/srv/http", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    33  20558 lstat64("/srv/http/family", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    34  20558 lstat64("/srv/http/family/index.html", 0x7ecec600) = -1 ENOENT (No such file or directory)
    35  20558 open("/srv/http/family/", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = 10
    36  20558 fstat64(10, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    37  20558 stat64("/srv/http/family/HEADER.html", 0x7ecec4a0) = -1 ENOENT (No such file or directory)
    38  20558 lstat64("/srv", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    39  20558 lstat64("/srv/http", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    40  20558 lstat64("/srv/http/family", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    41  20558 lstat64("/srv/http/family/HEADER.html", 0x7ecec4a0) = -1 ENOENT (No such file or directory)
    42  20558 getdents64(10, /* 5 entries */, 32768) = 160
    43  20558 lstat64("/srv/http/family/1977_Andrews_1.jpg", {st_mode=S_IFREG|0755, st_size=237934, ...}) = 0
    44  20558 lstat64("/srv/http/family/Locallink.jpg", {st_mode=S_IFLNK|0777, st_size=32, ...}) = 0
    45  20558 stat64("/srv/http/family/Locallink.jpg", {st_mode=S_IFREG|0755, st_size=237934, ...}) = 0
    46  20558 lstat64("/srv/http/family/.", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    47  20558 lstat64("/srv/http/family/CIFSlink.jpg", {st_mode=S_IFLNK|0777, st_size=64, ...}) = 0
    48  20558 stat64("/srv/http/family/CIFSlink.jpg", {st_mode=S_IFREG|0755, st_size=237934, ...}) = 0
    49  20558 lstat64("/srv/http/family/..", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    50  20558 getdents64(10, /* 0 entries */, 32768) = 0
    51  20558 close(10)                         = 0
    52  20558 stat64("/srv/http/family/README.html", 0x7ecec4a0) = -1 ENOENT (No such file or directory)
    53  20558 lstat64("/srv", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    54  20558 lstat64("/srv/http", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    55  20558 lstat64("/srv/http/family", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    56  20558 lstat64("/srv/http/family/README.html", 0x7ecec4a0) = -1 ENOENT (No such file or directory)
    57  20558 gettimeofday({tv_sec=1514078503, tv_usec=311917}, NULL) = 0
    58  20558 read(9, 0x3c9f60, 8000)           = -1 EAGAIN (Resource temporarily unavailable)
    59  20558 gettimeofday({tv_sec=1514078503, tv_usec=312941}, NULL) = 0
    60  20558 writev(9, [{iov_base="HTTP/1.1 200 OK\r\nDate: Sun, 24 D"..., iov_len=218}, {iov_base="<!DOCTYPE HTML PUBLIC \"-//W3C//D"..., iov_len=1112}], 2) = 1330
    61  20558 write(7, "192.168.0.107 - - [23/Dec/2017:2"..., 80) = 80
    62  20558 times({tms_utime=0, tms_stime=4, tms_cutime=0, tms_cstime=0}) = 953790583
    63  20558 gettimeofday({tv_sec=1514078503, tv_usec=316096}, NULL) = 0
    64  20558 poll([{fd=9, events=POLLIN}], 1, 5000 <unfinished ...>

The only vague thought remaining to me is that maybe there's some kind of timeout being tripped in the few milliseconds to get stuff over the CIFS share, but it seems like Apache of all servers should be fairly tolerant of latency. I don't think that has any real chance of being the answer and in any case I have no idea how to test it.

1

In a word, -noserverino. Per my original edits, the symlinks angle was a red herring and really so was the SMB/CIFS. It turns out Windows machines generate inode numbers larger than 32 bits, which the other programs can handle but PHP can't. -noseverino in the mount command tells the system to generate virtual inode numbers lower than 32 bits. PHP works as expected afterward.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.