diff --git a/libburn/ddlpa.c b/libburn/ddlpa.c index ece6d14..2dfebbe 100644 --- a/libburn/ddlpa.c +++ b/libburn/ddlpa.c @@ -3,6 +3,23 @@ Implementation of Delicate Device Locking Protocol level A. Copyright (C) 2007 Thomas Schmitt Provided under any of the following licenses: GPL, LGPL, BSD. Choose one. + + + Compile as test program: + + cc -g -Wall \ + -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1 -D_LARGEFILE64_SOURCE \ + -DDDLPA_C_STANDALONE -o ddlpa ddlpa.c + + The system macros are needed for 8-bit off_t and for open flag O_LARGEFILE + which are not absolutely necessary but explicitely take into respect that + our devices can offer more than 2 GB of addressable data. + + Run test program: + + ./ddlpa /dev/sr0 15 + ./ddlpa 0,0,0 15 + */ #include @@ -91,7 +108,7 @@ static int ddlpa_std_by_rdev(struct ddlpa_lock *o) if (ddlpa_debug_mode) fprintf(stderr, - "DDLPA_DEBUG: ddlpa_std_by_rdev(\"%s\") = \"%s\"\n", + "DDLPA_DEBUG: ddlpa_std_by_rdev(\"%s\") = \"%s\"\n", o->path, o->std_path); return 0; @@ -143,20 +160,32 @@ static int ddlpa_fcntl_lock(struct ddlpa_lock *o, int fd, int l_type) static int ddlpa_occupy(struct ddlpa_lock *o, char *path, int *fd, int no_o_excl) { - int ret, o_flags = O_RDWR | O_NDELAY; + int ret, o_flags, o_rw, l_type; + char *o_rwtext; + o_flags = o->o_flags | O_NDELAY; if(!no_o_excl) o_flags |= O_EXCL; + o_rw = (o_flags) & (O_RDONLY | O_WRONLY | O_RDWR); + o_rwtext = (o_rw == O_RDONLY ? "O_RDONLY" : + (o_rw == O_WRONLY ? "O_WRONLY" : + (o_rw == O_RDWR ? "O_RDWR " : "O_?rw-mode?"))); + *fd = open(path, o_flags); if (*fd == -1) { o->errmsg = malloc(strlen(path)+160); if (o->errmsg) sprintf(o->errmsg, - "Failed to open O_RDWR | O_NDELAY %s: '%s'", - (no_o_excl ? "" : "| O_EXCL "), path); + "Failed to open %s | O_NDELAY %s: '%s'", + o_rwtext, + (o_flags & O_EXCL ? "| O_EXCL " : ""), path); return (errno ? errno : EBUSY); } - ret = ddlpa_fcntl_lock(o, *fd, F_WRLCK); + if (o_rw == O_RDWR || o_rw == O_WRONLY) + l_type = F_WRLCK; + else + l_type = F_RDLCK; + ret = ddlpa_fcntl_lock(o, *fd, l_type); if (ret) { o->errmsg = malloc(strlen(path)+160); if (o->errmsg) @@ -167,7 +196,8 @@ static int ddlpa_occupy(struct ddlpa_lock *o, char *path, int *fd, return ret; } if (ddlpa_debug_mode) - fprintf(stderr, "DDLPA_DEBUG: ddlpa_occupy() %s: '%s'\n", + fprintf(stderr, "DDLPA_DEBUG: ddlpa_occupy() %s %s: '%s'\n", + o_rwtext, (no_o_excl ? " " : "O_EXCL "), path); return 0; } @@ -270,7 +300,7 @@ static int ddlpa_collect_siblings(struct ddlpa_lock *o) if (ddlpa_debug_mode) fprintf(stderr, - "DDLPA_DEBUG: ddlpa_collect_siblings() found \"%s\"\n", + "DDLPA_DEBUG: ddlpa_collect_siblings() found \"%s\"\n", try_path); (o->num_siblings)++; @@ -315,7 +345,7 @@ static int ddlpa_std_by_btl(struct ddlpa_lock *o) if (ddlpa_debug_mode) fprintf(stderr, - "DDLPA_DEBUG: ddlpa_std_by_rdev(%d,%d,%d) = \"%s\"\n", + "DDLPA_DEBUG: ddlpa_std_by_btl(%d,%d,%d) = \"%s\"\n", t_bus, t_id, t_lun, o->std_path); return 0; @@ -490,6 +520,14 @@ usage:; if (duration < 0) goto usage; + + /* For our purpose, only O_RDWR is a suitable access mode. + But in order to allow experiments, o_flags are freely adjustable. + + Warning: Do _not_ set an own O_EXCL flag with the following calls ! + + (This freedom to fail may get removed in a final version.) + */ if (my_path[0] != '/' && my_path[0] != '.' && strchr(my_path, ',') != NULL) { /* @@ -497,15 +535,17 @@ usage:; */ sscanf(my_path, "%d,%d,%d", &bus, &target, &lun); - ret = ddlpa_lock_btl(bus, target, lun, O_RDWR, 0, &lck, - &errmsg); + ret = ddlpa_lock_btl(bus, target, lun, O_RDWR | O_LARGEFILE, + 0, &lck, &errmsg); } else { /* This substitutes for: - fd = open(my_path, O_RDWR | O_EXCL); + fd = open(my_path, O_RDWR | O_EXCL | O_LARGEFILE); + */ - ret = ddlpa_lock_path(my_path, O_RDWR, 0, &lck, &errmsg); + ret = ddlpa_lock_path(my_path, O_RDWR | O_LARGEFILE, + 0, &lck, &errmsg); } if (ret) { fprintf(stderr, "Cannot exclusively open '%s'\n", my_path); diff --git a/libburn/ddlpa.h b/libburn/ddlpa.h index 090625d..6b057c9 100644 --- a/libburn/ddlpa.h +++ b/libburn/ddlpa.h @@ -51,7 +51,9 @@ struct ddlpa_lock { /** Lock a recorder by naming a device file path. Allocate a new container. @param path Gives the file system path of the recorder as known to the calling program. - @param o_flags flags for open(2) + @param o_flags flags for open(2). Do not use O_EXCL here because this + is done automatically whenever appropriate. + Advised is O_RDWR | O_LARGEFILE, eventually | O_NDELAY. @param ddlpa_flags 0 = default behavior: the standard path will be opened and treated by fcntl(F_SETLK) DDLPA_OPEN_GIVEN_PATH causes the input parameter "path" @@ -75,7 +77,7 @@ int ddlpa_lock_path(char *path, int o_flags, int ddlpa_flags, @param bus parameter to match ioctl(SCSI_IOCTL_GET_BUS_NUMBER) @param target parameter to match ioctl(SCSI_IOCTL_GET_IDLUN) &0xff @param lun parameter to match ioctl(SCSI_IOCTL_GET_IDLUN) &0xff00 - @param o_flags flags for open(2) + @param o_flags see ddlpa_lock_path(). @param ddlpa_flags see ddlpa_lock_path(). Flag DDLPA_OPEN_GIVEN_PATH will be ignored. @param lockbundle see ddlpa_lock_path().