Skip to content

Instantly share code, notes, and snippets.

@rrva
Created June 22, 2015 15:18
Show Gist options
  • Save rrva/48eeedd83563cbbbccec to your computer and use it in GitHub Desktop.
Save rrva/48eeedd83563cbbbccec to your computer and use it in GitHub Desktop.
iff --git a/mysys/my_fopen.c b/mysys/my_fopen.c
index ede434f..52dedba 100644
--- a/mysys/my_fopen.c
+++ b/mysys/my_fopen.c
@@ -185,6 +185,39 @@ static FILE *my_freebsd_freopen(const char *path, const char *mode, FILE *stream
#endif
+/**
+ Return a new file stream pointing to the same file
+ but ensure the file descriptor number is orig_fd.
+
+ Workaround for broken freopen() behavior
+ in glibc <= 2.13
+*/
+FILE* preserve_fd(FILE *stream, const int orig_fd)
+{
+ int flags= fcntl(orig_fd,F_GETFL);
+ int fd= fileno(stream);
+ int ret= dup2(fd,orig_fd);
+ if (ret < 0)
+ {
+ my_errno=errno;
+ my_error(EE_CANT_OPEN_STREAM, MYF(ME_BELL+ME_WAITTANG),errno);
+ return NULL;
+ }
+ char type[10];
+ make_ftype(type,flags);
+ FILE* result = fdopen(fd,type);
+ if (result)
+ {
+ fclose(stream);
+ return result;
+ }
+ else
+ {
+ my_errno=errno;
+ my_error(EE_CANT_OPEN_STREAM, MYF(ME_BELL+ME_WAITTANG),errno);
+ return NULL;
+ }
+}
/**
Change the file associated with a file stream.
@@ -217,7 +250,11 @@ FILE *my_freopen(const char *path, const char *mode, FILE *stream)
else
result= my_freebsd_freopen(path, mode, stream);
#else
+ int orig_fd = fileno(stream);
result= freopen(path, mode, stream);
+ if (result && fileno(result) != orig_fd) {
+ result= preserve_fd(result, orig_fd);
+ }
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment