Treating share modes as advisory when set by Mac clients

Brian Campbell lambda at editshare.com
Tue Mar 20 15:50:16 MDT 2012


On Wed, Mar 14, 2012 at 2:55 AM, Volker Lendecke
<Volker.Lendecke at sernet.de>wrote:

> On Tue, Mar 13, 2012 at 08:04:43PM +0100, Volker Lendecke wrote:
> > We need to fix "share modes = no" for you. It is highly
> > deprecated and will cause data corruption, but if it is
> > necessary to support OS/X, that's what you want. Probably
> > OS/X has its own secure mechanisms to protect against this
> > data corruption.
>
> To fix share modes = no, we need more information. In
> particular, it would be great to have a reproducer with
> stock OS/X Lion (which I have available).


Hi! Thanks for the offer to fix "share modes = no". Sorry it's taken me
some time to get back to you.

At the end of this message is a test program to reproduce this issue.

On a local filesystem, you can run from within one terminal:

  # Open somefile with O_EXLOCK
  open-test -l somefile

And in another terminal:

  # Open somefile with no locks
  open-test somefile

And both succeed in opening the file.

If you mount a Samba share on two machines, and do the above with a file in
the share, then the second open will fail; and it fails regardless of the
setting of "share modes = no".

If "share modes = no" were working, I would expect that the second open
would succeed whether or not we requested a lock in the second open.

Ideally, to match local filesystem semantics, there would be a way to make
share modes advisory (as I proposed in my initial message), not turn them
off entirely. If they are advisory, then you should be able to open the
file with a lock on one machine, and open it with no lock on another. But
the second open should fail if you try to open it with a lock on both
machines. Just fixing "share modes = no" will probably fix our problem, but
it won't be compatible with software that does depend on locks working when
both processes request a lock.

#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

void err_exit(char *msg, ...) {
  va_list ap;
  va_start(ap, msg);
  vfprintf(stderr, msg, ap);
  va_end(ap);

  exit(1);
}

void usage(char *name) {
  err_exit("Usage: %s [-l] filename\n", name);
}

int main(int argc, char *argv[]) {
  if (argc < 2 || argc > 3)
    usage(argv[0]);

  bool lock = false;
  bool flag = false;

  if (argc == 3) {
    flag = true;
    if (strcmp("-l", argv[1]))
      usage(argv[0]);
    else
      lock = true;
  }

  char *name = flag ? argv[2] : argv[1];
  int flags = O_WRONLY|O_CREAT|O_TRUNC|O_NONBLOCK;

  if (lock) {
    printf("Attempting to open %s with O_EXLOCK\n", name);
    flags |= O_EXLOCK;
  } else {
    printf("Attempting to open %s with no locks\n", name);
  }

  int fd = open(name, flags, 0664);
  if (fd < 0)
    err_exit("Couldn't open %s\n", name);

  printf("Opened %s. Press return to continue.\n", name);
  char buffer[2];
  fgets(buffer, sizeof(buffer), stdin);

  if (close(fd) < 0)
    err_exit("Couldn't close %s\n", name);

  return 0;
}

-- Brian


More information about the samba-technical mailing list