Also add a cloexec() method to turn close-on-exec off again.
#include <sys/utsname.h>
#include <sys/types.h>
#include <unistd.h>
+#include <fcntl.h>
/* argh, swig undefs bool for perl */
#ifndef bool
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;
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;
$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 {
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;
bless $self, $pkg if defined $self;
};
}
+#endif
~Chksum() {
solv_chksum_free($self, 0);
}
.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 \{\
.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
.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\&.
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 ===
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()
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.
$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;
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}};
}
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':
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()
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)
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
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
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]"
}
}