]> git.ipfire.org Git - thirdparty/libsolv.git/commitdiff
Make xfopen return file handles with close-on-exec set
authorMichael Schroeder <mls@suse.de>
Fri, 28 Aug 2015 13:42:59 +0000 (15:42 +0200)
committerMichael Schroeder <mls@suse.de>
Fri, 28 Aug 2015 13:42:59 +0000 (15:42 +0200)
Also add a cloexec() method to turn close-on-exec off again.

bindings/solv.i
doc/libsolv-bindings.3
doc/libsolv-bindings.txt
examples/p5solv
examples/pysolv
examples/rbsolv
examples/tclsolv

index 1c6128848d70b60eec7fee84fc900a26ec5c84b8..abf0db05ea1bd67531d5b61a5e65fc8d64d88ea1 100644 (file)
@@ -647,6 +647,7 @@ SWIG_AsValDepId(void *obj, int *val) {
 #include <sys/utsname.h>
 #include <sys/types.h>
 #include <unistd.h>
+#include <fcntl.h>
 
 /* argh, swig undefs bool for perl */
 #ifndef bool
@@ -1059,9 +1060,14 @@ SolvFp *solvfp_xfopen_fd(const char *fn, int fd, const char *mode = 0);
     SolvFp *sfp;
     FILE *fp;
     fd = dup(fd);
-    fp = fd == -1 ? 0 : solv_xfopen_fd(fn, fd, mode);
-    if (!fp)
+    if (fd == -1)
+      return 0;
+    fcntl(fd, F_SETFD, FD_CLOEXEC);
+    fp = solv_xfopen_fd(fn, fd, mode);
+    if (!fp) {
+      close(fd);
       return 0;
+    }
     sfp = solv_calloc(1, sizeof(SolvFp));
     sfp->fp = fp;
     return sfp;
@@ -1072,6 +1078,8 @@ SolvFp *solvfp_xfopen_fd(const char *fn, int fd, const char *mode = 0);
     fp = solv_xfopen(fn, mode);
     if (!fp)
       return 0;
+    if (fileno(fp) != -1)
+      fcntl(fileno(fp), F_SETFD, FD_CLOEXEC);
     sfp = solv_calloc(1, sizeof(SolvFp));
     sfp->fp = fp;
     return sfp;
@@ -1150,6 +1158,11 @@ typedef struct {
     $self->fp = 0;
     return ret;
   }
+  void cloexec(bool state) {
+    if (!$self->fp || fileno($self->fp) == -1)
+      return;
+    fcntl(fileno($self->fp), F_SETFD, state ? FD_CLOEXEC : 0);
+  }
 }
 
 %extend Job {
@@ -1339,6 +1352,7 @@ typedef struct {
   static Chksum *from_bin(Id type, const unsigned char *str, size_t len) {
     return len == solv_chksum_len(type) ? solv_chksum_create_from_bin(type, str) : 0;
   }
+#if defined(SWIGPERL)
   %perlcode {
     # make from_bin look like a constructor
     undef *solv::Chksum::from_bin;
@@ -1348,6 +1362,7 @@ typedef struct {
       bless $self, $pkg if defined $self;
     };
   }
+#endif
   ~Chksum() {
     solv_chksum_free($self, 0);
   }
index e07b229bd06c826581248875b77a057b6c4ab229..9fe26c13319d305fee24c7120baa71d245e3d86d 100644 (file)
@@ -5200,7 +5200,7 @@ my \fI$file\fR \fB= solv::xfopen_fd(\fR\fI$path\fR\fB,\fR \fI$fileno\fR\fB)\fR;
 .RE
 .\}
 .sp
-Create a file handle from the specified file descriptor\&. The path argument is only used to select the correct (de\-)compression algorithm, use an empty path if you want to make sure to read/write raw data\&.
+Create a file handle from the specified file descriptor\&. The path argument is only used to select the correct (de\-)compression algorithm, use an empty path if you want to make sure to read/write raw data\&. The file descriptor is dup()ed before the file handle is created\&.
 .SS "METHODS"
 .sp
 .if n \{\
@@ -5222,6 +5222,21 @@ Return file file descriptor of the file\&. If the file is not open, \-1 is retur
 .RS 4
 .\}
 .nf
+\fBvoid cloexec(bool\fR \fIstate\fR\fB)\fR
+\fI$file\fR\fB\->cloexec(\fR\fI$state\fR\fB)\fR
+\fIfile\fR\fB\&.cloexec(\fR\fIstate\fR\fB)\fR
+\fIfile\fR\fB\&.cloexec(\fR\fIstate\fR\fB)\fR
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+Set the close\-on\-exec flag of the file descriptor\&. The xfopen function returns files with close\-on\-exec turned on, so if you want to pass a file to some other process you need to call cloexec(0) before calling exec\&.
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
 \fBint dup()\fR
 my \fI$fileno\fR \fB=\fR \fI$file\fR\fB\->dup()\fR;
 \fIfileno\fR \fB=\fR \fIfile\fR\fB\&.dup()\fR
@@ -5261,7 +5276,7 @@ Flush the file\&. Returns false if there was an error\&. Flushing a closed file
 .RE
 .\}
 .sp
-Close the file\&. This is needed for languages like Ruby, that do not destruct objects right after they are no longer referenced\&. In that case, it is good style to close open files so that the file descriptors are freed right away\&. Returns false if there was an error\&.
+Close the file\&. This is needed for languages like Ruby that do not destruct objects right after they are no longer referenced\&. In that case, it is good style to close open files so that the file descriptors are freed right away\&. Returns false if there was an error\&.
 .SH "THE REPODATA CLASS"
 .sp
 The Repodata stores attributes for packages and the repository itself, each repository can have multiple repodata areas\&. You normally only need to directly access them if you implement lazy downloading of repository data\&. Repodata areas are created by calling the repository\(cqs add_repodata() method or by using repo_add methods without the REPO_REUSE_REPODATA or REPO_USE_LOADING flag\&.
index dcbc2d177e7e4961135e85fa4fc3e77a63b77780..175d922e2567e254fa419a0b737c349cfbd5aadb 100644 (file)
@@ -3195,7 +3195,8 @@ stdio library.
 
 Create a file handle from the specified file descriptor. The path argument is
 only used to select the correct (de-)compression algorithm, use an empty path
-if you want to make sure to read/write raw data.
+if you want to make sure to read/write raw data. The file descriptor is dup()ed
+before the file handle is created.
 
 === METHODS ===
 
@@ -3207,6 +3208,16 @@ if you want to make sure to read/write raw data.
 Return file file descriptor of the file. If the file is not open, `-1` is
 returned.
 
+       void cloexec(bool state)
+       $file->cloexec($state)
+       file.cloexec(state)
+       file.cloexec(state)
+
+Set the close-on-exec flag of the file descriptor. The xfopen function
+returns files with close-on-exec turned on, so if you want to pass
+a file to some other process you need to call cloexec(0) before calling
+exec.
+
        int dup()
        my $fileno = $file->dup();
        fileno = file.dup()
@@ -3228,7 +3239,7 @@ always returns true.
        file.close()
        file.close()
 
-Close the file. This is needed for languages like Ruby, that do not destruct
+Close the file. This is needed for languages like Ruby that do not destruct
 objects right after they are no longer referenced. In that case, it is good
 style to close open files so that the file descriptors are freed right away.
 Returns false if there was an error.
index 68be64f8da3666e36c815195a45b45d31f01e1ae..1f608cc77e4d78ce85b909c7eb537350e2a2e590 100755 (executable)
@@ -87,7 +87,7 @@ sub download {
   $url =~ s!/$!!;
   $url .= "/$file";
   open(my $f, '+>', undef) || die;
-  fcntl($f, Fcntl::F_SETFD, 0);
+  fcntl($f, Fcntl::F_SETFD, 0);                # turn of CLOEXEC
   my $st = system('curl', '-f', '-s', '-L', '-o', "/dev/fd/" . fileno($f), '--', $url);
   if (POSIX::lseek(fileno($f), 0, POSIX::SEEK_END) == 0 && ($st == 0 || !$chksum)) {
     return undef;
@@ -740,6 +740,7 @@ for my $p ($trans->steps()) {
     print "install ".$p->str()."\n";
     my $f = $newpkgsfps{$p->{id}};
     my $mode = $steptype == $solv::Transaction::SOLVER_TRANSACTION_INSTALL ? '-U' : '-i';
+    $f->cloexec(0);
     system('rpm', $mode, '--force', '--nodeps', '--nodigest', '--nosignature', "/dev/fd/".$f->fileno()) && die("rpm failed: $?\n");
     delete $newpkgsfps{$p->{id}};
   }
index 525623bc35d4cb061193774df008d59d7add7a03..3d6ca0714da98e514f6cfc1bb844ff3cdc908d97 100755 (executable)
@@ -303,7 +303,10 @@ class repo_generic(dict):
         return ''
 
     def add_ext_keys(self, ext, repodata, handle):
-        if ext == 'DU':
+        if ext == 'DL':
+            repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.REPOSITORY_DELTAINFO)
+            repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.REPOKEY_TYPE_FLEXARRAY)
+        elif ext == 'DU':
             repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.SOLVABLE_DISKUSAGE)
             repodata.add_idarray(handle, solv.REPOSITORY_KEYS, solv.REPOKEY_TYPE_DIRNUMNUMARRAY)
         elif ext == 'FL':
@@ -860,7 +863,7 @@ if newpkgs:
             continue
         if not sysrepo.handle.isempty() and os.access('/usr/bin/applydeltarpm', os.X_OK):
             pname = p.name
-            di = p.repo.meta.Dataiterator(solv.DELTA_PACKAGE_NAME, pname, solv.Dataiterator.SEARCH_STRING)
+            di = p.repo.Dataiterator_meta(solv.DELTA_PACKAGE_NAME, pname, solv.Dataiterator.SEARCH_STRING)
             di.prepend_keyname(solv.REPOSITORY_DELTAINFO)
             for d in di:
                 dp = d.parentpos()
@@ -887,6 +890,7 @@ if newpkgs:
                     continue
                 nf = tempfile.TemporaryFile()
                 nf = os.dup(nf.fileno())   # get rid of CLOEXEC
+                f.cloexec(0)
                 st = subprocess.call(['/usr/bin/applydeltarpm', '-a', p.arch, "/dev/fd/%d" % f.fileno(), "/dev/fd/%d" % nf])
                 if st:
                     os.close(nf)
index 144a0dd848e3fecea4263891267e0327bfbf3549..be633f3caf42ef14468b157bf7e1874bf27d0ba4 100755 (executable)
@@ -755,6 +755,7 @@ for p in trans.steps
     f = newpkgsfp.delete(p.id)
     next unless f
     mode = steptype == Solv::Transaction::SOLVER_TRANSACTION_INSTALL ? '-U' : '-i'
+    f.cloexec(0)
     system('rpm', mode, '--force', '--nodeps', '--nodigest', '--nosignature', "/dev/fd/#{f.fileno().to_s}") || abort("rpm failed: #{$? >> 8}")
     f.close
   end
index 27e1466ea33b3cf56267174c173bff3a21283713..6f819aa73b9ecefb095195d90b89b75b2a01360d 100755 (executable)
@@ -212,6 +212,9 @@ proc repo_generic_add_ext_keys {selfName ext repodata h} {
   if {$ext eq "DL"} {
     $repodata add_idarray $h $solv::REPOSITORY_KEYS $solv::REPOSITORY_DELTAINFO
     $repodata add_idarray $h $solv::REPOSITORY_KEYS $solv::REPOKEY_TYPE_FLEXARRAY
+  } elseif {$ext eq "DU"} {
+    $repodata add_idarray $h $solv::REPOSITORY_KEYS $solv::SOLVABLE_DISKUSAGE
+    $repodata add_idarray $h $solv::REPOSITORY_KEYS $solv::REPOKEY_TYPE_DIRNUMNUMARRAY
   } elseif {$ext eq "FL"} {
     $repodata add_idarray $h $solv::REPOSITORY_KEYS $solv::SOLVABLE_FILELIST
     $repodata add_idarray $h $solv::REPOSITORY_KEYS $solv::REPOKEY_TYPE_DIRSTRARRAY
@@ -794,6 +797,7 @@ foreach p [$trans steps] {
     puts "install [$p str]"
     set f $newpkgs_f([$p cget -id])
     set mode [expr {$steptype == $solv::Transaction_SOLVER_TRANSACTION_INSTALL ? "-U" : "-i"}]
+    $f cloexec 0
     exec -ignorestderr -- rpm $mode --force --nodeps --nodigest --nosignature "/dev/fd/[$f fileno]"
   }
 }