2 # Functions for cygwin + redhat package management
4 use vars '$hasrpm'; $hasrpm = (-f "/usr/bin/rpm.exe");
5 use vars '$db'; $db = "/etc/setup/installed.db";
7 sub validate_package_system
9 return -r $db ? undef : &text('cygwin_edb', "<tt>$db</tt>");
12 # list_packages([package]*)
13 # Fills the array %packages with all or listed packages
17 my $allpkgs = (@_ == 0);
18 local($i, $list); $i = 0;
20 if (&open_tempfile(DB, $db)) {
22 #suppress packages that begin with an underscore
23 if (/^([^_][^\s]*)\s+([^\s]+)\s+(\d+)/) {
24 #TODO: classes, descriptions
25 my ($name, $ver, $class, $desc) = ($1, $2, "cygwin", "");
26 my $qmname = quotemeta($name);
27 next if ! $allpkgs && ! grep(/^$qmname$/, @pkgs);
28 $ver =~ s/.*?[_\-](\d.*)\.tar\..*/$1/;
29 $packages{$i, 'name'} = $name;
30 $packages{$i, 'class'} = $class;
31 $packages{$i, 'version'} = $ver;
32 $packages{$i, 'desc'} = $desc;
34 @pkgs = grep { $_ ne $name } @pkgs if ! $allpkgs;
36 last if (! $allpkgs && @pkgs == 0);
41 return $i if ! $hasrpm || (! $allpkgs && @pkgs == 0);
43 $list = @_ ? join(' ', map { quotemeta($_) } @_) : "-a";
44 &open_execute_command(RPM, "rpm -q $list --queryformat \"%{NAME}\\n%{VERSION}-%{RELEASE}\\n%{GROUP}\\n%{SUMMARY}\\n\\n\"", 1, 1);
45 while($packages{$i,'name'} = <RPM>) {
46 chop($packages{$i,'name'});
47 chop($packages{$i,'version'} = <RPM>);
48 chop($packages{$i,'class'} = <RPM>);
52 $packages{$i,'desc'} .= $_;
60 # package_info(package, version)
61 # Returns an array of package information in the order
62 # name, class, description, arch, version, vendor, installtime
65 my @cygdata = cygwin_pkg_info(@_);
66 return @cygdata if @cygdata > 0;
67 return undef if ! $hasrpm;
70 local $n = $_[1] ? "$_[0]-$_[1]" : $_[0];
71 local $qm = quotemeta($n);
72 &open_execute_command(RPM, "rpm -q $qm --queryformat \"%{NAME}\\n%{GROUP}\\n%{ARCH}\\n%{VERSION}-%{RELEASE}\\n%{VENDOR}\\n%{INSTALLTIME}\\n\" 2>/dev/null", 1, 1);
75 if (!@tmp) { return (); }
77 &open_execute_command(RPM, "rpm -q $qm --queryformat \"%{DESCRIPTION}\"", 1, 1);
78 while(<RPM>) { $d .= $_; }
80 return ($tmp[0], $tmp[1], $d, $tmp[2], $tmp[3], $tmp[4], &make_date($tmp[5]));
84 # Check if some file is a package file
88 local $real = &translate_filename($_[0]);
90 # a directory .. see if it contains any .rpm or .tar.bz2 files
92 local @list = grep { /([^\s]+[_\-](\d[^\s]*|src)-\d[^\s]*\.tar\.bz2|\.rpm)$/} readdir(DIR);
96 elsif ($_[0] =~ /\*|\?/) {
97 # a wildcard .. see what it matches
98 local @list = glob($real);
102 # just a normal file ..check if it is an RPM and not an SRPM or tar.bz2
103 return 1 if $_[0] =~ /[^\s]+[_\-](\d[^\s]*|src)-\d[^\s]*\.tar\.bz2$/;
104 local $qm = quotemeta($_[0]);
105 $out = &backquote_command("rpm -q -p $qm 2>&1", 1);
106 if ($out =~ /does not appear|No such file|with major numbers/i) {
109 &open_execute_command(OUT, "rpm -q -p -l $qm 2>&1", 1, 1);
111 return 0 if (/^([^\/\s]+)\.spec$/);
118 # file_packages(file)
119 # Returns a list of all packages in the given file, in the form
120 # package-version description
123 local $real = &translate_filename($_[0]);
124 local $qm = quotemeta($_[0]);
128 @rv = grep { s/.*\/([^\s]+)[_\-]((\d[^\s]*|src)-\d[^\s]*)\.tar\.bz2$/$1/ } readdir(DIR);
130 &open_execute_command(RPM, "cd $qm && rpm -q -p *.rpm --queryformat \"%{NAME} %{SUMMARY}\\n\" 2>&1", 1, 1);
133 push(@rv, $_) if (!/does not appear|query of.*failed|warning:/);
138 elsif ($_[0] =~ /\*|\?/) {
140 my @p = &backquote_command("ls $_[0]");
141 @rv = grep { s/.*\/([^\s]+)[_\-]((\d[^\s]*|src)-\d[^\s]*)\.tar\.bz2$/$1/ } @p;
142 &open_execute_command(RPM, "rpm -q -p $_[0] --queryformat \"%{NAME} %{SUMMARY}\\n\" 2>&1", 1);
145 push(@rv, $_) if (!/does not appear|query of.*failed|warning:/);
154 if $out =~ s/.*\/([^\s]+)[_\-]((\d[^\s]*|src)-\d[^\s]*)\.tar\.bz2$/$1/;
155 $out = &backquote_command("rpm -q -p $qm --queryformat \"%{NAME} %{SUMMARY}\\n\" 2>&1", 1);
156 $out =~ s/warning:.*\n//;
162 # install_options(file, package)
163 # Outputs HTML for choosing install options for some package
166 my ($file, $pkg) = @_;
167 if ($file =~ /\/[^\s]+[_\-]src[_\-]\d[^\s]*\.tar\.bz2$/) {
169 } elsif ($file =~ /\/[^\s]+[_\-]\d[^\s]*-\d[^\s]*\.tar\.bz2$/) {
170 print &ui_table_row(undef, "<b>$text{'cygwin_warnuse'}</b>", 4);
172 print &yesno_input($text{'rpm_upgrade'}, "upgrade", 1, 0, 1);
173 print &yesno_input($text{'rpm_replacepkgs'}, "replacepkgs", 1, 0);
175 print &yesno_input($text{'rpm_noscripts'}, "noscripts", 0, 1);
177 print &yesno_input($text{'rpm_upgrade'}, "upgrade", 1, 0, 1);
178 print &yesno_input($text{'rpm_replacepkgs'}, "replacepkgs", 1, 0);
180 print &yesno_input($text{'rpm_nodeps'}, "nodeps", 1, 0);
181 print &yesno_input($text{'rpm_oldpackage'}, "oldpackage", 1, 0);
183 print &yesno_input($text{'rpm_noscripts'}, "noscripts", 0, 1);
184 print &yesno_input($text{'rpm_excludedocs'}, "excludedocs", 0, 1);
186 print &yesno_input($text{'rpm_notriggers'}, "notriggers", 0, 1);
187 print &yesno_input($text{'rpm_ignoresize'}, "ignoresize", 0, 1);
189 print &yesno_input($text{'rpm_replacefiles'}, "replacefiles", 1, 0);
191 print &ui_table_row(&hlink($text{'rpm_root'}, "root"),
192 &ui_textbox("root", "/", 50)." ".
193 &file_chooser_button("root", 1), 3);
198 return &ui_table_row(&hlink($_[0], $_[1]),
199 &ui_radio($_[1], int($_[4]),
200 [ [ $_[2], $text{'yes'} ],
201 [ $_[3], $text{'no'} ] ]));
204 # install_package(file, package, [&inputs])
205 # Install the given package from the given file, using options from %in
209 local $real = &translate_filename($file);
210 local $in = $_[2] ? $_[2] : \%in;
212 foreach $o ('oldpackage', 'replacefiles', 'replacepkgs', 'noscripts',
213 'excludedocs', 'nodeps', 'upgrade', 'notriggers', 'ignoresize') {
214 if ($in->{$o}) { $opts .= " --$o"; }
216 if ($in->{'root'} =~ /^\/.+/) {
217 if (!(-d $in{'root'})) {
218 return &text('rpm_eroot', $in->{'root'});
220 $opts .= " --root $in->{'root'}";
223 # Find the package in the directory
226 while($f = readdir(DIR)) {
227 if ($f =~ /\/([^\s]+[_\-]src[_\-]\d[^\s]*)\.tar\.bz2$/) {
229 } elsif ($f =~ /^([^\s]+[_\-]\d[^\s]*-\d[^\s]*)\.tar\.bz2$/) {
232 next if ($f !~ /\.rpm$/);
233 $out = &backquote_command("rpm -q -p $file/$f --queryformat \"%{NAME}\\n\" 2>&1");
234 $out =~ s/warning:.*\n//;
243 &error(&text('rpm_erpm', $_[1], $out)) if ($file eq $_[0]);
245 elsif ($file =~ /\*|\?/) {
246 # Find the package in the glob
247 # XXX won't work when translation is in effect
249 foreach $f (glob($real)) {
250 if ($f =~ /\/([^\s]+[_\-]src[_\-]\d[^\s]*)\.tar\.bz2$/) {
252 } elsif ($f =~ /\/([^\s]+[_\-]\d[^\s]*-\d[^\s]*)\.tar\.bz2$/) {
255 $out = &backquote_command("rpm -q -p $f --queryformat \"%{NAME}\\n\" 2>&1", 1);
256 $out =~ s/warning:.*\n//;
264 &error(&text('rpm_erpm', $_[1], $out)) if ($file eq $_[0]);
266 local $temp = &transname();
268 if ($file =~ /\/[^\s]+[_\-]src[_\-]\d[^\s]*\.tar\.bz2$/) {
269 $rv = install_cygwin_src_pkg($file, $temp, $in->{'root'});
270 } elsif ($file =~ /\/[^\s]+[_\-]\d[^\s]*-\d[^\s]*\.tar\.bz2$/) {
272 $run_scripts = 0 if defined($in->{'noscripts'}) && $in->{'noscripts'} == 1;
273 $rv = install_cygwin_pkg($file, $temp, $in->{'root'}, $run_scripts,
274 $in->{'replacepkgs'}, $in->{'upgrade'});
276 $rv = &system_logged("rpm -i $opts ".quotemeta($file)." >$temp 2>&1");
279 if (! open(FILE, "<$temp")) {
280 warn "could not open $temp: $!\n";
282 $out = join('', <FILE>);
284 $out =~ s/warning:.*\n//;
288 return "<pre>$out</pre>";
293 #instead of defining install_packages() (which do_install.cgi has a
294 #couple of design flaws with), make it install them one-by-one.
295 #<<- no sub install_packages here ->>
297 # check_files(package, version)
298 # Fills in the %files array with information about the files belonging
299 # to some package. Values in %files are path type user group size error
302 local($i, $_, @w, %errs, $epath); $i = 0;
303 my @cygdata = cygwin_pkg_info(@_);
305 my $origlst = "${root}etc/setup/$cygdata[0].lst.gz";
306 if (@cygdata && -f $origlst) {
307 #$name, $class, $desc, $arch, $ver, $vendor, $date
308 my $lst = uncompress_if_needed($origlst);
309 if (&open_readfile(FILES, $lst)) {
312 my $f = get_file_info($root . $_);
313 for (qw(path link type user group size error)) {
314 $files{$i, $_} = $f->{$_} if defined($f->{$_});
319 &unlink_file($lst) if $origlst ne $lst;
322 return $i if $i > 0 || ! $hasrpm;
324 local $n = $_[1] ? "$_[0]-$_[1]" : $_[0];
325 local $qm = quotemeta($n);
326 &open_execute_command(RPM, "rpm -V $qm", 1, 1);
329 if ($1 eq "missing ") {
330 $errs{$3} = $text{'rpm_missing'};
334 @w = grep { $_ ne "." } split(//, $1);
336 join("\n", map { &text('rpm_checkfail', $etype{$_}) } @w);
340 &open_execute_command(RPM, "rpm -q $qm -l --dump", 1, 1);
344 $files{$i,'path'} = $w[0];
345 if ($w[10] ne "X") { $files{$i,'link'} = $w[10]; }
346 $files{$i,'type'} = $w[10] ne "X" ? 3 :
347 (-d &translate_filename($w[0])) ? 1 :
349 $files{$i,'user'} = $w[5];
350 $files{$i,'group'} = $w[6];
351 $files{$i,'size'} = $w[1];
352 $files{$i,'error'} = $w[7] ? "" : $errs{$w[0]};
359 # installed_file(file)
360 # Given a filename, fills %file with details of the given file and returns 1.
361 # If the file is not known to the package system, returns 0
362 # Usable values in %file are path type user group mode size packages
365 local($pkg, @w, $_, @pkgs, @vers);
371 local $qm = quotemeta($file);
372 @pkgs = &backquote_command("zgrep -le '^$qm\$' /etc/setup/*.lst.gz 2>&1", 1);
375 grep(s/.*etc\/setup\/(.+)\.lst\.gz/$1/g, @pkgs);
376 my $f = get_file_info($root . $file);
377 $f->{'packages'} = join(' ', @pkgs);
378 if (&open_readfile(LST, $db)) {
380 if (/^([^\s]+)\s+[^\s]+[_\-]([\d][^\s]\.tar\.bz2)\s/) {
381 my ($pkg, $ver) = ($1, $2);
382 $f->{'versions'} .= "$ver "
383 if grep(/^$pkg$/, @pkgs);
391 return 0 if ! $hasrpm;
394 local $qm = quotemeta($_[0]);
395 $pkg = &backquote_command("rpm -q -f $qm --queryformat \"%{NAME}\\n\" 2>&1", 1);
396 if ($pkg =~ /not owned/ || $?) { return 0; }
397 @pkgs = split(/\n/, $pkg);
398 $pkg = &backquote_command("rpm -q -f $qm --queryformat \"%{VERSION}-%{RELEASE}\\n\" 2>&1");
399 @vers = split(/\n/, $pkg);
400 &open_execute_command(RPM, "rpm -q $pkgs[0] -l --dump", 1, 1);
404 if ($w[0] eq $_[0]) {
405 $file{'packages'} = join(' ', @pkgs);
406 $file{'versions'} = join(' ', @vers);
407 $file{'path'} = $w[0];
408 if ($w[10] ne "X") { $files{$i,'link'} = $w[10]; }
409 $file{'type'} = $w[10] ne "X" ? 3 :
410 (-d &translate_filename($w[0])) ? 1 :
412 $file{'user'} = $w[5];
413 $file{'group'} = $w[6];
414 $file{'mode'} = substr($w[4], -4);
415 $file{'size'} = $w[1];
423 # delete_options(package)
424 # Outputs HTML for package uninstall options
427 my @cygdata = cygwin_pkg_info(@_);
429 print "<b>$text{'cygwin_warnuse'}</b><br>\n";
431 print "<b>$text{'delete_nodeps'}</b>\n";
432 print &ui_yesno_radio("nodeps", 0),"<br>\n";
434 print "<b>$text{'delete_noscripts'}</b>\n";
435 print &ui_yesno_radio("noscripts", 0),"<br>\n";
438 # delete_package(package, [&options], version)
439 # Attempt to remove some package
442 local $in = $_[2] ? $_[2] : \%in;
443 my @cygdata = cygwin_pkg_info($_[0], $_[2]);
447 $run_scripts = 0 if (defined($in->{'noscripts'}) &&
448 $in->{'noscripts'} == 1);
449 local $temp = &transname();
450 my $rv = remove_cygwin_pkg($_[0], $temp, $root, $run_scripts);
451 if ($rv && &open_readfile(FILE, $temp)) {
452 my $out = join('', <FILE>);
455 return "<pre>$out</pre>" if $rv;
461 $opts .= $_[1]->{'nodeps'} ? "--nodeps " : "";
462 $opts .= $_[1]->{'noscripts'} ? "--noscripts " : "";
463 local $n = $_[2] ? "$_[0]-$_[2]" : $_[0];
464 local $qm = quotemeta($n);
465 local $out = &backquote_logged("rpm -e $opts $qm 2>&1");
466 if ($? || $out =~ /error:/) { return "<pre>$out</pre>"; }
470 # delete_packages(&packages, [&options], &versions)
471 # Attempt to remove multiple packages at once
475 $opts .= $_[1]->{'nodeps'} ? "--nodeps " : "";
476 $opts .= $_[1]->{'noscripts'} ? "--noscripts " : "";
477 local $cmd = "rpm -e $opts";
479 for($i=0; $i<@{$_[0]}; $i++) {
481 $cmd .= " ".quotemeta($_[0]->[$i]."-".$_[2]->[$i]);
484 $cmd .= " ".quotemeta($_[0]->[$i]);
487 local $out = &backquote_logged("$cmd 2>&1");
488 if ($? || $out =~ /error:/) { return "<pre>$out</pre>"; }
495 $text .= "/RPM" if $hasrpm;
504 %etype = ( "5", $text{'rpm_md5'}, "S", $text{'rpm_fsize'},
505 "L", $text{'rpm_sym'}, "T", $text{'rpm_mtime'},
506 "D", $text{'rpm_dev'}, "U", $text{'rpm_user'},
507 "M", $text{'rpm_perm'}, "G", $text{'rpm_group'} );
509 $has_search_system = 1;
511 sub search_system_input
513 print "<input type=button onClick='window.ifield = document.forms[2].url; chooser = window.open(\"rpmfind.cgi\", \"chooser\", \"toolbar=no,menubar=no,scrollbars=yes,width=600,height=500\")' value=\"$text{'rpm_find'}\">";
516 # file, temp output file, root path
517 sub install_cygwin_src_pkg
519 my ($file, $temp, $root) = @_;
520 $root .= "/" if $root =~ /[^\/]$/;
522 &system_logged("mkdir -p $root > $temp 2>&1") if ! -d $root;
524 $opts .= " -C $root";
526 $pkg =~ s/[_\-]\d.*//;
527 my $rv = &system_logged("tar $opts -f ".quotemeta($file).
532 # file, temp output file, root path, run_scripts, replace pkgs, upgrade
533 sub install_cygwin_pkg
535 my ($file, $temp, $root, $run_scripts, $replace_pkgs, $upgrade) = @_;
537 $root .= "/" if $root =~ /[^\/]$/;
538 &system_logged("mkdir -p $root > $temp 2>&1") if ! -d $root;
540 $opts .= " -C $root";
542 $pkg =~ s/.*\/(.+?)[_\-]\d.*/$1/;
543 my $setupdir = "${root}etc/setup";
544 my $lstfile = "$setupdir/$pkg.lst";
546 #the only time we don't check for the same package currently installed
547 #is if the user specified to replace pkgs but not to upgrade
549 unless (! $upgrade && $replace_pkgs) {
550 #check to see if a package is already installed
551 @cygdata = cygwin_pkg_info($pkg);
552 if (@cygdata && $upgrade) {
553 remove_cygwin_pkg($cygdata[0], $temp, $root, $run_scripts);
556 if (@cygdata && ! $upgrade && ! $replace_pkgs) {
557 if (&open_tempfile(FILE, ">>$temp", 1)) {
558 &print_tempfile(FILE, &text('cygwin_pkgexists', $pkg) . "\n");
559 &close_tempfile(FILE);
564 &system_logged("mkdir -p $setupdir") if ! -d $setupdir;
565 my $rv = &system_logged("tar $opts -f ".quotemeta($file).
566 " > $lstfile 2>>$temp");
567 if ($run_scripts && open(FILE, "<$lstfile")) {
568 #run postinstall scripts
570 if (/etc\/postinstall\/.*sh/) {
571 my $f = quotemeta($_);
572 $rv += &system_logged("sh $root$f >> $temp 2>&1");
573 $rv += &system_logged("mv -v $root$f $root$f.done>>$temp 2>&1");
578 $rv += &system_logged("gzip -f $lstfile >>$temp 2>&1");
579 my $db = "$setupdir/installed.db";
581 if (open(FILE, "<$db")) {
584 #avoid windows security issues
585 &system_logged("chmod u+w $db >>$temp 2>&1") if ! -w $db;
586 &system_logged("chown $ENV{'USERNAME'} $db >>$temp 2>&1")
589 if (&open_tempfile(FILE, ">$db", 1)) {
590 #remove the package from the db if it already exists
591 @lines = grep {! /^$pkg /} @lines;
592 #add this package to the end.
593 push(@lines, "$pkg $file 0\n");
594 &print_tempfile(FILE, @lines);
595 &close_tempfile(FILE);
602 # pkg, temp output file, root path, run_scripts
603 sub remove_cygwin_pkg
605 my ($pkg, $temp, $root, $run_scripts) = @_;
606 $root .= "/" if $root =~ /[^\/]$/;
607 my $setupdir = "${root}etc/setup";
608 my $lstfile = "$setupdir/$pkg.lst.gz";
611 my @cygdata = cygwin_pkg_info($pkg);
613 if (&open_tempfile(FILE, ">$temp", 1)) {
614 &print_tempfile(FILE, "Could not find $pkg\n");
615 &close_tempfile(FILE);
618 #kludge: don't get rid of packages on which we depend
619 } elsif ($pkg =~ /^(perl|webmin|gzip|tar|bzip2|cygwin|ash)$/) {
620 if (&open_tempfile(FILE, ">$temp", 1)) {
621 &print_tempfile(FILE, "Not removing $pkg because of dependencies.\n");
622 &print_tempfile(FILE, "You'll have to force installation of the package.\n");
623 &close_tempfile(FILE);
626 #load in the list file
627 } elsif (! -f $lstfile || ! open(LST, "gunzip -c $lstfile |")) {
629 if (&open_tempfile(FILE, ">$temp")) {
630 &print_tempfile(FILE, "Could not open $lstfile\n");
631 &close_tempfile(FILE);
638 #run preremove scripts
640 my @scripts = grep(/^etc\/preremove\/.*sh/, @files);
642 my $f = quotemeta($_);
643 $rv += system_logged("sh $root$f >> $temp 2>&1");
644 $rv += system_logged("mv -v $root$f $root$f.done>>$temp 2>&1");
648 #remove all files except files in etc
649 foreach (reverse(@files)) {
652 my $msg = &unlink_logged($_)? "" : $!;
655 my $msg = &unlink_logged($_)? "" : $!;
660 #run postremove scripts
662 my @scripts = grep(/^etc\/postremove\/.*sh/, @files);
664 my $f = quotemeta($_);
665 $rv += system_logged("sh $root$f >> $temp 2>&1");
666 $rv += system_logged("mv -v $root$f $root$f.done>>$temp 2>&1");
670 $rv += system_logged("rm -f $lstfile >>$temp 2>&1");
671 my $db = "$setupdir/installed.db";
673 if (&open_readfile(FILE, $db)) {
676 if (&open_tempfile(FILE, ">$db")) {
677 #remove the package from the db
678 @lines = grep {! /^$pkg /} @lines;
679 &print_tempfile(FILE, @lines);
680 &close_tempfile(FILE);
688 #returns: name, class, description, arch, version, vendor, installtime
691 my ($pkg_name, $pkg_ver) = @_;
692 if (&open_readfile(DB, $db)) {
694 if (/^([^\s]*)\s+([^\s]+)\s+(\d+)/) {
695 #TODO: classes, descriptions, vendor, installtime, arch
696 my ($name, $ver, $class, $desc) = ($1, $2, "cygwin", "");
697 next if $name ne $pkg_name;
698 $ver =~ s/.*?[_\-]([\d+].*)\.tar\..*/$1/;
699 next if defined($pkg_ver) && $pkg_ver ne $ver;
700 my ($arch, $vendor, $date) = ("i586", "cygwin", undef);
701 if (@_ = stat(&translate_filename("/etc/setup/$name.lst.gz"))) {
702 $date = make_date($_[9]);
705 return ($name, $class, $desc, $arch, $ver, $vendor, $date)
713 # Usable values in %file are path type user group mode size packages
717 my $predetected_error = "";
719 #check to make sure if it is a post install script that it was run
720 if ($f =~ /\/etc\/postinstall\/.*\.sh$/) {
722 $predetected_error = $text{'cygwin_badpostscript'};
724 #automatically change postinstall script to be .done
725 #since it does not exist
726 $f =~ s%(/etc/postinstall/.*\.sh)$%$1.done%;
731 my $real = &translate_filename($f);
733 if (! -l $real && ! -e $real) {
734 $file{'error'} = $text{'cygwin_fmissing'};
737 $file{'error'} = $predetected_error;
738 if (@_ = stat($real)) {
739 my @ent = getpwuid($_[4]);
740 $file{'user'} = (@ent && $ent[0] ne "????????")?
742 @ent = getgrgid($_[5]);
743 $file{'group'} = (@ent && $ent[0] ne "????????")?
745 $file{'size'} = $_[7];
746 $file{'mode'} = sprintf "%o", $_[2] & 07777;
750 if (@_ = lstat($real)) {
751 my @ent = getpwuid($_[4]);
752 $file{'user'} = (@ent && $ent[0] ne "????????")?
754 @ent = getgrgid($_[5]);
755 $file{'group'} = (@ent && $ent[0] ne "????????")?
757 $file{'size'} = $_[7];
758 $file{'mode'} = sprintf "%o", $_[2] & 07777;
759 if ($file{'link'} = readlink($real)) {
760 my $l = $file{'link'};
761 my $lreal = &translate_filename($l);
762 my $fb = $f; $fb =~ s/[^\/]*$//;
763 $l = $fb . $l if $l !~ /^\//;
764 if (! -l $lreal && ! -e $lreal) {
765 $file{'error'} = $text{'cygwin_lmissing'};
767 $file{'error'} = $predetected_error;
770 $file{'error'} = &text('cygwin_elread', $!);
773 $file{'error'} = &text('cygwin_elstat', $!);
776 #2 = special file; 0 = regular file
777 $file{'type'} = (-f $real)? 0 : 2;
778 if (@_ = stat($real)) {
779 my @ent = getpwuid($_[4]);
780 $file{'user'} = (@ent && $ent[0] ne "????????")?
782 @ent = getgrgid($_[5]);
783 $file{'group'} = (@ent && $ent[0] ne "????????")?
785 $file{'size'} = $_[7];
786 $file{'mode'} = sprintf "%o", $_[2] & 07777;
787 $file{'error'} = $predetected_error;
789 $file{'error'} = &text('cygwin_estat', $!);