Save and restore errno in raw1394_new_handle{,_on_port} for legacy applications
Since dual-stack capability was added to libraw1394, raw1394_new_handle() and raw1394_new_handle_on_port() began to alter errno even when succeeding. This breaks old application code which contains the bug of checking for failure in errno rather than in the return code of said functions, or similar bugs with wrong assumptions about errno. While those applications should be fixed, it may not always be possible or feasible to do so. Hence add a workaround to libraw1394 which saves and restores errno in said two functions. From a superficial review of dispatch.c, it seems that these two functions are the only ones where such a workaround may be needed. However, this may not be true if any fw_XYZ() function implementation differs from the counterpart ieee1394_XYZ() function in the way that the former alters errno during successful execution while the latter does not. To be clear, altering errno in absence of failure is absolutely allowed in library code (except for signal handlers), yet it may be unexpected and be perceived as a library or kernel regression if the application client code is buggy in this regard. Reported-by: Vladimir Romanov <blueboar2@gmail.com> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
This commit is contained in:
parent
ba8d2119ba
commit
d80678dc55
|
@ -28,11 +28,14 @@ raw1394handle_t raw1394_new_handle(void)
|
||||||
fw_handle_t fw_handle;
|
fw_handle_t fw_handle;
|
||||||
raw1394handle_t handle;
|
raw1394handle_t handle;
|
||||||
struct raw1394_portinfo port;
|
struct raw1394_portinfo port;
|
||||||
|
int errno_bak;
|
||||||
|
|
||||||
handle = (raw1394handle_t) malloc(sizeof(struct raw1394_handle));
|
handle = (raw1394handle_t) malloc(sizeof(struct raw1394_handle));
|
||||||
if (!handle)
|
if (!handle)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
errno_bak = errno; /* workaround for faulty legacy applications */
|
||||||
|
|
||||||
ieee1394_handle = ieee1394_new_handle();
|
ieee1394_handle = ieee1394_new_handle();
|
||||||
if (!ieee1394_handle)
|
if (!ieee1394_handle)
|
||||||
goto try_fw;
|
goto try_fw;
|
||||||
|
@ -44,6 +47,8 @@ raw1394handle_t raw1394_new_handle(void)
|
||||||
}
|
}
|
||||||
ieee1394_destroy_handle(ieee1394_handle);
|
ieee1394_destroy_handle(ieee1394_handle);
|
||||||
try_fw:
|
try_fw:
|
||||||
|
errno = errno_bak;
|
||||||
|
|
||||||
fw_handle = fw_new_handle();
|
fw_handle = fw_new_handle();
|
||||||
if (fw_handle) {
|
if (fw_handle) {
|
||||||
handle->is_fw = 1;
|
handle->is_fw = 1;
|
||||||
|
@ -72,11 +77,14 @@ raw1394handle_t raw1394_new_handle_on_port(int port)
|
||||||
ieee1394handle_t ieee1394_handle;
|
ieee1394handle_t ieee1394_handle;
|
||||||
fw_handle_t fw_handle;
|
fw_handle_t fw_handle;
|
||||||
raw1394handle_t handle;
|
raw1394handle_t handle;
|
||||||
|
int errno_bak;
|
||||||
|
|
||||||
handle = (raw1394handle_t) malloc(sizeof(struct raw1394_handle));
|
handle = (raw1394handle_t) malloc(sizeof(struct raw1394_handle));
|
||||||
if (!handle)
|
if (!handle)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
errno_bak = errno; /* workaround for faulty legacy applications */
|
||||||
|
|
||||||
ieee1394_handle = ieee1394_new_handle_on_port(port);
|
ieee1394_handle = ieee1394_new_handle_on_port(port);
|
||||||
if (ieee1394_handle) {
|
if (ieee1394_handle) {
|
||||||
handle->is_fw = 0;
|
handle->is_fw = 0;
|
||||||
|
@ -84,6 +92,8 @@ raw1394handle_t raw1394_new_handle_on_port(int port)
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errno = errno_bak;
|
||||||
|
|
||||||
fw_handle = fw_new_handle_on_port(port);
|
fw_handle = fw_new_handle_on_port(port);
|
||||||
if (fw_handle) {
|
if (fw_handle) {
|
||||||
handle->is_fw = 1;
|
handle->is_fw = 1;
|
||||||
|
|
Reference in New Issue