From nobody Tue Nov 15 07:49:48 2022 X-Original-To: dev-commits-ports-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4NBJHK1Hr4z4hFPF; Tue, 15 Nov 2022 07:49:49 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4NBJHK0wLxz3pC7; Tue, 15 Nov 2022 07:49:49 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1668498589; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=RvJ7XpRZjsye75mUUaxFXoXoiydXgzKuEkARdKPpPjg=; b=IbASSlZ7mlgNykR2VfrcbNnhmlXTCpqI9Kmog2T5oZ2xuJfhDx8Z5UllDmrJXBU8OZa8Al G092W5yilLJlnc6uRAY8Fj0ydyF7aiF2JMVwmMd2ij2SlBrsqQf2mCOWybDKZReC0CdeAz W7g9KcNR0Hw/TTNVvPE9glhPISkN6oEfXmRgIRBcIX5b8+BSJC54xXmYcFKxIEJ39Cee8R nJhxJbbNE31YDGaK293zjzOdkKKL9jK92+MUqAjJTUQ4S9hKMByBCVtpG+Xpejdi0TrN9A eEnc6LYvnpuGRCtJb+atf5dNxx/aWIhvlxlrE8dxkzUkIYlIYWFxuhQwbMHsRQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1668498589; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=RvJ7XpRZjsye75mUUaxFXoXoiydXgzKuEkARdKPpPjg=; b=sh75VSfiVIlxG+icwFaRU68wou2T/jeeeSB6kstkJz6BNp0ZhWbFA8iyTQD/YBomjxa9wC dnGFIwQAX20T1JP2hPej+Oo6MyeUniPOPJ9ZASW5oeAaOa7dLLsIJkrKt9HEBA0Ft48QYn RI49p3qyPzwaSdy7ZbWsl1F2zxkH7S5ZttkW8VH3uv2wfEdbxmoMWLNlvQK+2L79txE7cI Si6USLo/uPRiqmYGZgCGNALkBR+yVd8zAOHHr5rF+uEfl4+J+KhkzQ5RwHXfScAGZ+2ca6 WEPsW2bLFi+AYic5d1UB2BeMw07VtOidR8CVR8AMWNLDjI0TS7wgc9QY8zVZ9g== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1668498589; a=rsa-sha256; cv=none; b=cKxRLARFXkjLHP+hGvkUF6IyU9/FpAd7rvLgJzHvWVWXYXd3e0tAYB7H1TLYIN49Cf7Uhb 8xaGTZ+da3xlrL4NX8B4Jd3SUNLikNIMojFoKUtS7v9c2PDFlYeNkv1qzpRXRU61k8m0t2 cEY4fgB+8bO623WFdmw4EGElErJwTS6DoYrTBnaIBNtE6bvOC1I7wyfuL9R4ILUaJKKAt7 Cf9LGCSwvrczmXApYiqN+R2wJ7hxXKXyLU4nT6a2UewD2ck7f4kUBTETyVhLoQQ6B9LYPH XaoHFuAoU+lV61NXCNxkbh+OAq/K4ucbc78qvHb1qnQkbtho/hYSB5hWr1TiRA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4NBJHJ6rhYzDk0; Tue, 15 Nov 2022 07:49:48 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 2AF7nmKB075769; Tue, 15 Nov 2022 07:49:48 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 2AF7nmdk075768; Tue, 15 Nov 2022 07:49:48 GMT (envelope-from git) Date: Tue, 15 Nov 2022 07:49:48 GMT Message-Id: <202211150749.2AF7nmdk075768@gitrepo.freebsd.org> To: ports-committers@FreeBSD.org, dev-commits-ports-all@FreeBSD.org, dev-commits-ports-main@FreeBSD.org From: Alexey Dokuchaev Subject: git: 7863be845544 - main - x11-fm/4pane: new port had been added (+) List-Id: Commit messages for all branches of the ports repository List-Archive: https://lists.freebsd.org/archives/dev-commits-ports-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-ports-all@freebsd.org X-BeenThere: dev-commits-ports-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: danfe X-Git-Repository: ports X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 7863be845544d90c80f6e4d71ef0da9eda30b4dc Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by danfe: URL: https://cgit.FreeBSD.org/ports/commit/?id=7863be845544d90c80f6e4d71ef0da9eda30b4dc commit 7863be845544d90c80f6e4d71ef0da9eda30b4dc Author: Alexey Dokuchaev AuthorDate: 2022-11-15 07:47:42 +0000 Commit: Alexey Dokuchaev CommitDate: 2022-11-15 07:47:42 +0000 x11-fm/4pane: new port had been added (+) 4Pane is a multi-pane, detailed-list file manager for Unix-like systems. It is designed to be fully-featured without bloat, and aims for speed rather than visual effects. The program relies on some GNU/Linux utilities and API to manage disks and mounts. Non-portable calls to getmntent(3) et al. had been replaced with our native getmntinfo(3) ones. However, full storage support is still lacking, owing to limited blkid(8) and lsblk(8) functionality and inconsistent naming of different file systems between GNU/Linux and FreeBSD. --- x11-fm/4pane/Makefile | 23 +++ x11-fm/4pane/distinfo | 3 + x11-fm/4pane/files/patch-Devices.cpp | 342 +++++++++++++++++++++++++++++++++++ x11-fm/4pane/files/patch-Devices.h | 26 +++ x11-fm/4pane/files/patch-Misc.cpp | 33 ++++ x11-fm/4pane/files/patch-Mounts.cpp | 102 +++++++++++ x11-fm/4pane/pkg-descr | 6 + x11-fm/4pane/pkg-plist | 196 ++++++++++++++++++++ x11-fm/Makefile | 1 + 9 files changed, 732 insertions(+) diff --git a/x11-fm/4pane/Makefile b/x11-fm/4pane/Makefile new file mode 100644 index 000000000000..78a4ef999717 --- /dev/null +++ b/x11-fm/4pane/Makefile @@ -0,0 +1,23 @@ +PORTNAME= 4pane +PORTVERSION= 7.0 +CATEGORIES= x11-fm +MASTER_SITES= SF/fourpane/${PORTVERSION} + +MAINTAINER= danfe@FreeBSD.org +COMMENT= Multi-pane, detailed-list graphical file manager +WWW= http://www.4pane.co.uk/ + +LICENSE= GPLv3 + +USES= pkgconfig +USE_WX= 3.0+ +GNU_CONFIGURE= yes +CONFIGURE_ARGS= --with-wx-config="${WX_CONFIG}" + +OPTIONS_DEFINE= NLS +OPTIONS_SUB= yes + +NLS_USES= gettext +NLS_CONFIGURE_OFF= --disable-locale + +.include diff --git a/x11-fm/4pane/distinfo b/x11-fm/4pane/distinfo new file mode 100644 index 000000000000..9947c9110125 --- /dev/null +++ b/x11-fm/4pane/distinfo @@ -0,0 +1,3 @@ +TIMESTAMP = 1607257783 +SHA256 (4pane-7.0.tar.gz) = 09716c4000ba193db128d97d04e6bc8c9dfebf11e2755bfc071ce1db339d8b80 +SIZE (4pane-7.0.tar.gz) = 2113199 diff --git a/x11-fm/4pane/files/patch-Devices.cpp b/x11-fm/4pane/files/patch-Devices.cpp new file mode 100644 index 000000000000..8866393bd213 --- /dev/null +++ b/x11-fm/4pane/files/patch-Devices.cpp @@ -0,0 +1,342 @@ +--- Devices.cpp.orig 2020-11-22 11:42:51 UTC ++++ Devices.cpp +@@ -1357,7 +1357,7 @@ if (!wxFileExists(BLKID)) + if (wxFileExists(wxT("/usr/bin/blkid"))) BLKID = wxT("/usr/bin/blkid"); + else + { wxArrayString output, errors;long ans; +- if (wxGetOsDescription().Contains(wxT("kFreeBSD"))) // The kFreeBSD forkpty hangs ++ if (wxGetOsDescription().Contains(wxT("FreeBSD"))) // FreeBSD's forkpty() hangs + ans = wxExecute(wxT("which blkid"), output, errors); + else + ans = ExecuteInPty(wxT("which blkid"), output, errors); +@@ -1371,7 +1371,7 @@ if (!wxFileExists(LSBLK)) + if (wxFileExists(wxT("/sbin/lsblk"))) LSBLK = wxT("/sbin/lsblk"); + else + { wxArrayString output, errors; long ans; +- if (wxGetOsDescription().Contains(wxT("kFreeBSD"))) ++ if (wxGetOsDescription().Contains(wxT("FreeBSD"))) + ans = wxExecute(wxT("which lsblk"), output, errors); + else + ans = ExecuteInPty(wxT("which lsblk"), output, errors); +@@ -1590,14 +1590,22 @@ bool DeviceAndMountManager::Checkmtab(wxString& mountp + return DeviceAndMountManager::GnuCheckmtab(mountpoint, device); + #endif + ++#ifdef __linux__ + struct mntent* mnt = NULL; + + FILE* fmp = setmntent (_PATH_MOUNTED, "r"); // Get a file* to (probably) /etc/mtab + if (fmp==NULL) return false; ++#else ++struct statfs* fslist; + ++int numfs = getmntinfo(&fslist, MNT_NOWAIT); ++if (numfs < 1) return false; ++#endif ++ + wxString mountpt(mountpoint); FileData mp(mountpt); + if (mp.IsSymlink()) mountpt = mp.GetUltimateDestination(); // Cope with a symlink + ++#ifdef __linux__ + while (1) // For every mtab entry + { mnt = getmntent(fmp); // Get a struct representing a mounted partition + if (mnt == NULL) +@@ -1605,14 +1613,24 @@ while (1) + + wxString mntdir(mnt->mnt_dir, wxConvUTF8); + wxString type(mnt->mnt_type, wxConvUTF8); type.MakeLower(); ++#else ++for (int i = 0; i < numfs; ++i) ++ { wxString mntdir(fslist[i].f_mntonname, wxConvUTF8); ++ wxString type(fslist[i].f_fstypename, wxConvUTF8); type.MakeLower(); ++#endif + // Don't try to create a FileData if we're testing a network mount. It's less likely to be symlinked, and e.g. a stale nfs mount hangs lstat! + if (!type.StartsWith(wxT("nfs")) && !type.Contains(wxT("sshfs")) && type != wxT("cifs") && type != wxT("smbfs")) + { FileData mt(mntdir); if (mt.IsSymlink()) mntdir = mt.GetUltimateDestination(); } // Cope with a symlink + if (mntdir == mountpt) // This is the one we're looking for ++#ifdef __linux__ + { endmntent(fmp); + if (device.IsEmpty()) return true; // If we don't care which device is mounted there + + wxString mntfsname(mnt->mnt_fsname, wxConvUTF8); // in case we DO care ++#else ++ { if (device.IsEmpty()) return true; ++ wxString mntfsname(fslist[i].f_mntfromname, wxConvUTF8); ++#endif + FileData dev(device); FileData mntfs(mntfsname); // Cope with any symlinks + if (dev.IsSymlink()) device = dev.GetUltimateDestination(); + if (mntfs.IsSymlink()) mntfsname = mntfs.GetUltimateDestination(); +@@ -1649,6 +1667,7 @@ wxString DeviceAndMountManager::WhereIsDeviceMounted(w + + wxString DeviceAndMountManager::WhereIsDeviceMounted(wxString device, size_t type) + { ++#ifdef __linux__ + struct mntent* mnt = NULL; + + FILE* fmp = setmntent (_PATH_MOUNTED, "r"); // Get a file* to (probably) /etc/mtab +@@ -1660,6 +1679,17 @@ while (1) + wxString mntfsname(mnt->mnt_fsname, wxConvUTF8); + if (mntfsname == device) + { endmntent(fmp); return wxString(mnt->mnt_dir, wxConvUTF8); } // If it's the one we're looking for, return the associated mountpt ++#else ++struct statfs* fslist; ++ ++int numfs = getmntinfo(&fslist, MNT_NOWAIT); ++if (numfs < 1) return wxEmptyString; ++ ++for (int i = 0; i < numfs; ++i) ++ { wxString mntfsname(fslist[i].f_mntfromname, wxConvUTF8); ++ if (mntfsname == device) ++ return wxString(fslist[i].f_mntonname, wxConvUTF8); ++#endif + } + + // If we're here, the device wasn't found. See if it's actually a symlink for a different device eg /dev/dvd -> /dev/hdc. If so, try that +@@ -1678,17 +1708,27 @@ return wxEmptyString; + } + + //static ++#ifdef __linux__ + struct mntent* DeviceAndMountManager::ReadMtab(const wxString& partition, bool DvdRamFS /*=false*/) // Is 'partition' currently mounted? Returns struct of data if it is, NULL if it isn't + { + struct mntent* mnt = NULL; + + FILE* fmp = setmntent (_PATH_MOUNTED, "r"); // Get a file* to (probably) /etc/mtab + if (fmp==NULL) return mnt; ++#else ++struct statfs* DeviceAndMountManager::ReadMtab(const wxString& partition, bool DvdRamFS /*=false*/) ++{ ++struct statfs* fslist; + ++int numfs = getmntinfo(&fslist, MNT_NOWAIT); ++if (numfs < 1) return NULL; ++#endif ++ + wxString partitionwithsep(partition), partitionwithout(partition); // Avoid the usual '/' issue + if (partition.Right(1) == wxFILE_SEP_PATH) partitionwithout = partition.BeforeLast(wxFILE_SEP_PATH); + else partitionwithsep << wxFILE_SEP_PATH; + ++#ifdef __linux__ + while (1) // For every mtab entry + { mnt = getmntent(fmp); // Get a struct representing a mounted partition + if (mnt == NULL) break; // If it's null, we've run out of candidates. Return null as flag +@@ -1706,6 +1746,22 @@ mnt = NULL; return mnt; + if (stat.IsSymlink()) { wxString target = stat.GetSymlinkDestination(); return ReadMtab(target, DvdRamFS); } + + mnt = NULL; return mnt; // If we're here, it failed. Return null as flag ++#else ++for (int i = 0; i < numfs; ++i) ++ { wxString mntfsname(fslist[i].f_mntfromname, wxConvUTF8); ++ if (!mntfsname.empty() && ((mntfsname == partitionwithsep) || (mntfsname == partitionwithout))) ++ { if (!DvdRamFS) return &fslist[i]; ++ wxString mnttype(fslist[i].f_fstypename, wxConvUTF8); ++ for (size_t n=0; n < RealFilesystemsArray.GetCount(); ++n) ++ if (mnttype.Left(3) == RealFilesystemsArray.Item(n).Left(3)) return &fslist[i]; ++ } ++ } ++FileData stat(partition); ++if (stat.IsSymlink()) ++ { wxString target = stat.GetSymlinkDestination(); ++ return ReadMtab(target, DvdRamFS); ++ } else return NULL; ++#endif + } + + +@@ -1887,14 +1943,25 @@ if (!FillPartitionArrayUsingLsblk(true)) + { pstruct->mountpt = wxString(fs->fs_file, wxConvUTF8); // Store the mountpt + pstruct->IsMounted = Checkmtab(pstruct->mountpt, pstruct->device);// & whether it's mounted. Pass the device-name too, so that we only record if the mountpt contains THIS device + if (!pstruct->IsMounted) // If it isn't mounted where it's supposed to be, look elsewhere in case it was su-mounted in the 'wrong' place ++#ifdef __linux__ + { struct mntent* mnt = ReadMtab(pstruct->device); + if (mnt != NULL) { pstruct->mountpt = wxString(mnt->mnt_dir, wxConvUTF8); pstruct->IsMounted = true; } ++#else ++ { struct statfs* mnt = ReadMtab(pstruct->device); ++ if (mnt != NULL) { pstruct->mountpt = wxString(mnt->f_mntonname, wxConvUTF8); pstruct->IsMounted = true; } ++#endif + } + } + else // If we didn't find it in fstab, check mtab anyway, in case someone mounted it the hard way ++#ifdef __linux__ + { struct mntent* mnt = ReadMtab(pstruct->device); + if (mnt != NULL) + { pstruct->mountpt = wxString(mnt->mnt_dir, wxConvUTF8); // Store the mountpt ++#else ++ { struct statfs* mnt = ReadMtab(pstruct->device); ++ if (mnt != NULL) ++ { pstruct->mountpt = wxString(mnt->f_mntonname, wxConvUTF8); ++#endif + pstruct->IsMounted = true; // It's mounted by definition: it's in mtab + } + else pstruct->IsMounted = false; // Otherwise reset this bool, as it's otherwise undefined +@@ -2027,6 +2094,7 @@ void DeviceAndMountManager::FindMountedImages() // Ad + + void DeviceAndMountManager::FindMountedImages() // Add mounted iso-images from mtab to array + { ++#ifdef __linux__ + FILE* fmp = setmntent (_PATH_MOUNTED, "r"); // Get a file* to (probably) /etc/mtab + if (fmp==NULL) return; + +@@ -2036,12 +2104,26 @@ while (1) + { endmntent(fmp); return; } // If it's null, we've finished mtab + + wxString device(mnt->mnt_fsname, wxConvUTF8); // Make the 'device' into a wxString for convenience ++#else ++struct statfs* fslist; ++ ++int numfs = getmntinfo(&fslist, MNT_NOWAIT); ++if (numfs < 1) return; ++ ++for (int i = 0; i < numfs; ++i) ++ { wxString device(fslist[i].f_mntfromname, wxConvUTF8); ++#endif + // If it starts with a '/dev/loop' or with a '/' but not with /dev/ or // it's probably an iso-image + if ((device.Left(9) == wxT("/dev/loop")) || (device.GetChar(0) == wxT('/') && + !(device.Left(5) == wxT("/dev/") || device.Left(2) == wxT("//")))) + { struct PartitionStruct* newmnt = new struct PartitionStruct; // store in structarray ++#ifdef __linux__ + newmnt->device = wxString(mnt->mnt_fsname, wxConvUTF8); + newmnt->mountpt = wxString(mnt->mnt_dir, wxConvUTF8); ++#else ++ newmnt->device = wxString(fslist[i].f_mntfromname, wxConvUTF8); ++ newmnt->mountpt = wxString(fslist[i].f_mntonname, wxConvUTF8); ++#endif + newmnt->IsMounted = true; // By definition + PartitionArray->Add(newmnt); + } +@@ -2153,6 +2235,7 @@ for (size_t n=0; n < partitions.GetCount(); ++n) + for (size_t n=0; n < partitions.GetCount(); ++n) + { wxString item = partitions.Item(n); + if (item == dev || item == symtarget) ++#ifdef __linux__ + { struct mntent* mnt = NULL; // Found an entry. Look for it in mtab + FILE* fmp = setmntent (_PATH_MOUNTED, "r"); if (fmp==NULL) { endfsent(); return answerarray.GetCount() > 0; } + while (1) +@@ -2166,6 +2249,16 @@ for (size_t n=0; n < partitions.GetCount(); ++n) + if (wxString(mnt->mnt_dir,wxConvUTF8) == mountpts.Item(n)) // but it's already mounted here + { endmntent(fmp); break; } // so look in 'partitions' array for another entry + } ++#else ++ { struct statfs* fslist; ++ int numfs = getmntinfo(&fslist, MNT_NOWAIT); ++ if (numfs < 1) return answerarray.GetCount() > 0; ++ for (int i = 0; i < numfs; ++i) ++ if (wxString(fslist[i].f_mntfromname, wxConvUTF8) == dev || wxString(fslist[i].f_mntfromname, wxConvUTF8) == symtarget) ++ if (wxString(fslist[i].f_mntonname, wxConvUTF8) == mountpts.Item(n)) goto another; ++ answerarray.Add(mountpts.Item(n)); ++another:; ++#endif + } + } + +@@ -2921,8 +3014,13 @@ for (size_t n=0; n < allpartitions.GetCount(); ++n) + { if (allpartitions[n].Left(len) == dev.Left(len)) // If the 1st 'len' letters of the NAME bit of this partition match dev ie /dev/sda1 matches /dev/sda + { partitions.Add(allpartitions[n]); // store it in the real partition array + ++#ifdef __linux__ + struct mntent* mnt = ReadMtab(allpartitions[n]); // Now see if this partition is currently mounted + if (mnt != NULL) mountpts.Add(wxString(mnt->mnt_dir, wxConvUTF8)); // If so, store the mountpt ++#else ++ struct statfs* mnt = ReadMtab(allpartitions[n]); ++ if (mnt != NULL) mountpts.Add(wxString(mnt->f_mntonname, wxConvUTF8)); ++#endif + else mountpts.Add(wxEmptyString); // Otherwise store "" + } + } +@@ -2944,7 +3042,11 @@ wxTextFile file; // + void DeviceAndMountManager::CheckSupermountTab(wxArrayString& partitions, wxArrayString& mountpts, wxString dev, bool SearchMtab) // In Supermount systems, finds data for this device + { + wxTextFile file; // Create a textfile ++#ifdef __linux__ + if (SearchMtab) file.Create(wxT(_PATH_MOUNTED)); // using mtab ++#else ++if (SearchMtab) return; ++#endif + else file.Create(wxT(_PATH_FSTAB)); // or fstab + if (!file.Exists()) return; + file.Open(); if (!file.IsOpened()) return; +@@ -2971,17 +3073,27 @@ void DeviceAndMountManager::SearchMtab(wxArrayString& + + void DeviceAndMountManager::SearchMtab(wxArrayString& partitions, wxArrayString& mountpts, wxString dev /*=wxEmptyString*/) // Loads arrays with data for the named device, or for all devices. NB Only finds mounted partitions + { ++#ifdef __linux__ + struct mntent* mnt = NULL; ++#else ++struct statfs* fslist; ++#endif + + partitions.Empty(); mountpts.Empty(); // Empty the arrays of any old data: we don't want to append! + ++#ifdef __linux__ + FILE* fmp = setmntent (_PATH_MOUNTED, "r"); // Get a file* to (probably) /etc/mtab + if (fmp==NULL) return; ++#else ++int numfs = getmntinfo(&fslist, MNT_NOWAIT); ++if (numfs < 1) return; ++#endif + + wxString mask; + if (dev.IsEmpty()) mask = AUTOMOUNT_USB_PREFIX; // We normally search for all AUTOMOUNT_USB_PREFIX devices, probably "/dev/sd" + else mask = dev; // but if dev isn't empty, use this instead + ++#ifdef __linux__ + while (1) // For every mtab entry + { mnt = getmntent(fmp); // Get a struct representing a mounted partition + if (mnt == NULL) { endmntent(fmp); return; } // If it's null, we've run out of candidates +@@ -2990,18 +3102,29 @@ while (1) // + if (wxString(mnt->mnt_fsname, wxConvUTF8).Left(mask.Len()) == mask) + { partitions.Add(wxString(mnt->mnt_fsname, wxConvUTF8)); // If so, store the devnode and mountpt + mountpts.Add(wxString(mnt->mnt_dir, wxConvUTF8)); ++#else ++for (int i = 0; i < numfs; ++i) ++ { if (wxString(fslist[i].f_mntfromname, wxConvUTF8).Left(mask.Len()) == mask) ++ { partitions.Add(wxString(fslist[i].f_mntfromname, wxConvUTF8)); ++ mountpts.Add(wxString(fslist[i].f_mntonname, wxConvUTF8)); ++#endif + } + } + } + + void DeviceAndMountManager::SearchMtabForStandardMounts(wxString& device, wxArrayString& mountpts) // Finds ext2 etc mountpts for the device ie not subfs. Used for DVD-RAM + { ++#ifdef __linux__ + struct mntent* mnt = NULL; ++#else ++struct statfs* fslist; ++#endif + mountpts.Empty(); // Empty the array of any old data: we don't want to append! + + wxString symtarget; FileData fd(device); // Beware of the symlink + if (fd.IsSymlink()) symtarget = fd.GetUltimateDestination(); + ++#ifdef __linux__ + FILE* fmp = setmntent (_PATH_MOUNTED, "r"); // Get a file* to (probably) /etc/mtab + if (fmp==NULL) return; + +@@ -3012,12 +3135,26 @@ while (1) // + bool found = false; + if (wxString(mnt->mnt_fsname, wxConvUTF8).Left(device.Len()) == device) found=true; // See if this is a mount for the device we're interested in + else if (!symtarget.IsEmpty() && wxString(mnt->mnt_fsname, wxConvUTF8).Left(symtarget.Len()) == symtarget) found=true; // Try again with any symlink target ++#else ++int numfs = getmntinfo(&fslist, MNT_NOWAIT); ++if (numfs < 1) return; + ++for (int i = 0; i < numfs; ++i) ++ { bool found = false; ++ if (wxString(fslist[i].f_mntfromname, wxConvUTF8).Left(device.Len()) == device) found=true; ++ else if (!symtarget.IsEmpty() && wxString(fslist[i].f_mntfromname, wxConvUTF8).Left(symtarget.Len()) == symtarget) found=true; ++#endif ++ + if (!found) continue; // Wrong device + + for (size_t n=0; n < RealFilesystemsArray.GetCount(); ++n) // For DVD-RAM, we're only interested in filesystems like ext2 not eg subfs ++#ifdef __linux__ + if (wxString(mnt->mnt_type, wxConvUTF8).Left(3) == RealFilesystemsArray.Item(n).Left(3)) + { mountpts.Add(wxString(mnt->mnt_dir, wxConvUTF8)); break; } // If the type is right, this mountpt is one we want to store ++#else ++ if (wxString(fslist[i].f_fstypename, wxConvUTF8).Left(3) == RealFilesystemsArray.Item(n).Left(3)) ++ { mountpts.Add(wxString(fslist[i].f_mntonname, wxConvUTF8)); break; } ++#endif + } + } + diff --git a/x11-fm/4pane/files/patch-Devices.h b/x11-fm/4pane/files/patch-Devices.h new file mode 100644 index 000000000000..12ffcf07852a --- /dev/null +++ b/x11-fm/4pane/files/patch-Devices.h @@ -0,0 +1,26 @@ +--- Devices.h.orig 2020-11-22 11:43:42 UTC ++++ Devices.h +@@ -13,7 +13,11 @@ + #include "wx/config.h" + + #include ++#ifdef __linux__ + #include ++#else ++#include ++#endif + + #include "Externs.h" + +@@ -310,7 +314,11 @@ void OnUnMountNetwork(); + void OnMountSshfs(); + void OnMountSamba(); + void OnUnMountNetwork(); ++#ifdef __linux__ + static struct mntent* ReadMtab(const wxString& partition, bool DvdRamFS=false); // Goes thru mtab, to find if 'partition' currently mounted. If DvdRamFS, ignores eg subfs mounts (used for DVD-RAM) ++#else ++static struct statfs* ReadMtab(const wxString& partition, bool DvdRamFS=false); ++#endif + static struct fstab* ReadFstab(const wxString& dev, const wxString& uuid = "", const wxString& label = ""); // Search fstab for a line for this device + static struct fstab* ReadFstab(const PartitionStruct* ps) { return ReadFstab(ps->device, ps->uuid, ps->label); } + static bool FindUnmountedFstabEntry(wxString& dev, wxArrayString& answerarray); // Ditto but only returning Unmounted entries. Used for DVD-RAM diff --git a/x11-fm/4pane/files/patch-Misc.cpp b/x11-fm/4pane/files/patch-Misc.cpp new file mode 100644 index 000000000000..fc3e96fbcf6f --- /dev/null +++ b/x11-fm/4pane/files/patch-Misc.cpp @@ -0,0 +1,33 @@ +--- Misc.cpp.orig 2020-11-19 18:24:13 UTC ++++ Misc.cpp +@@ -511,7 +511,7 @@ wxArrayString output, errors; + wxCHECK_MSG(!lib.empty(), "", "Empty parameter"); + + wxArrayString output, errors; +-long ans = wxExecute("sh -c \"/sbin/ldconfig -p | grep " + lib + '\"', output,errors); ++long ans = wxExecute("sh -c \"/sbin/ldconfig -r | grep " + lib + '\"', output,errors); + if (ans != 0 || output.IsEmpty()) return ""; + + wxString fpath = output.Item(0).AfterLast(' '); +@@ -666,7 +666,12 @@ if (clientDC) delete clientDC; + #endif + //----------------------------------------------------------------------------------------------------------------------- + ++#ifdef __linux__ + #include ++#else ++#include ++#include ++#endif + #include + #include + +@@ -779,7 +784,7 @@ if (cmd.empty()) return ERROR_RETURN_CODE; + { + if (cmd.empty()) return ERROR_RETURN_CODE; + +-if (wxGetOsDescription().Contains(wxT("kFreeBSD"))) // The kFreeBSD forkpty hangs ++if (wxGetOsDescription().Contains(wxT("FreeBSD"))) // FreeBSD's forkpty() hangs + { if (GetCallerTextCtrl()) + InformCallerOnTerminate(); + return ERROR_RETURN_CODE; diff --git a/x11-fm/4pane/files/patch-Mounts.cpp b/x11-fm/4pane/files/patch-Mounts.cpp new file mode 100644 index 000000000000..b0f4b6d28554 --- /dev/null +++ b/x11-fm/4pane/files/patch-Mounts.cpp @@ -0,0 +1,102 @@ +--- Mounts.cpp.orig 2020-11-22 11:42:50 UTC ++++ Mounts.cpp +@@ -866,8 +866,13 @@ for (size_t n=0; n < parent->PartitionArray->GetCount( + if (parent->PartitionArray->Item(n)->device == dev.BeforeFirst(' ')) // BeforeFirst in case of "/dev/sda1 $UUID/$LABEL" + { if (GetDataFromMtab) // If we're unmounting, we can't rely on the PartitionArray info: the partition may not have been mounted where fstab intended + { FstabMountptTxt->Clear(); ++#ifdef __linux__ + struct mntent* mnt = parent->ReadMtab(dev.BeforeFirst(' ')); // So see where it really is + if (mnt != NULL) FstabMountptTxt->ChangeValue(wxString(mnt->mnt_dir, wxConvUTF8)); ++#else ++ struct statfs* mnt = parent->ReadMtab(dev.BeforeFirst(' ')); ++ if (mnt != NULL) FstabMountptTxt->ChangeValue(wxString(mnt->f_mntonname, wxConvUTF8)); ++#endif + return; + } + else +@@ -968,10 +973,18 @@ FstabMt = (InFstab ? wxString(fs->fs_file, wxConvUTF8) + InFstab = (fs != NULL); // Store or null the data according to the result + FstabMt = (InFstab ? wxString(fs->fs_file, wxConvUTF8) : wxT("")); + ++#ifdef __linux__ + struct mntent* mnt = DeviceAndMountManager::ReadMtab(Image); // Now read mtab to see if the share's already mounted ++#else ++struct statfs* mnt = DeviceAndMountManager::ReadMtab(Image); ++#endif + IsMounted = (mnt != NULL); + AlreadyMounted->Show(IsMounted); GetSizer()->Layout(); // If it is mounted, expose the wxStaticTxt that says so (and Layout, else 2.8.0 displays it in top left corner!) ++#ifdef __linux__ + AtMountPt = (IsMounted ? wxString(mnt->mnt_dir, wxConvUTF8) : wxT("")); // Store any mountpt, or delete any previous entry ++#else ++AtMountPt = (IsMounted ? wxString(mnt->f_mntonname, wxConvUTF8) : wxT("")); ++#endif + if (IsMounted) + MountptCombo->SetValue(AtMountPt); // Put any mountpt in the combobox + else if (InFstab) +@@ -1209,11 +1222,19 @@ FstabMt = (InFstab ? wxString(fs->fs_file, wxConvUTF8) + InFstab = (fs != NULL); // Store or null the data according to the result + FstabMt = (InFstab ? wxString(fs->fs_file, wxConvUTF8) : wxT("")); + ++#ifdef __linux__ + struct mntent* mnt = DeviceAndMountManager::ReadMtab(device1); // Now read mtab to see if the share's already mounted ++#else ++struct statfs* mnt = DeviceAndMountManager::ReadMtab(device1); ++#endif + if (mnt == NULL) mnt = DeviceAndMountManager::ReadMtab(device2); // Null means not found, so try again with the IP version + IsMounted = (mnt != NULL); + AlreadyMounted->Show(IsMounted); GetSizer()->Layout(); // If it is mounted, expose the wxStaticTxt that says so (and Layout, else 2.8.0 displays it in top left corner!) ++#ifdef __linux__ + AtMountPt = (IsMounted ? wxString(mnt->mnt_dir, wxConvUTF8) : wxT("")); // Store any mountpt, or delete any previous entry ++#else ++AtMountPt = (IsMounted ? wxString(mnt->f_mntonname, wxConvUTF8) : wxT("")); ++#endif + if (IsMounted) + MountptCombo->SetValue(AtMountPt); + else if (InFstab) +@@ -1503,10 +1524,18 @@ FstabMt = (InFstab ? wxString(fs->fs_file, wxConvUTF8) + InFstab = (fs != NULL); // Store or null the data according to the result + FstabMt = (InFstab ? wxString(fs->fs_file, wxConvUTF8) : wxT("")); + ++#ifdef __linux__ + mntent* mnt = DeviceAndMountManager::ReadMtab(device); // Now read mtab to see if the share's already mounted ++#else ++struct statfs* mnt = DeviceAndMountManager::ReadMtab(device); ++#endif + IsMounted = (mnt != NULL); + AlreadyMounted->Show(IsMounted); GetSizer()->Layout(); // If it is mounted, expose the wxStaticTxt that says so (and Layout, else 2.8.0 displays it in top left corner!) ++#ifdef __linux__ + AtMountPt = (IsMounted ? wxString(mnt->mnt_dir, wxConvUTF8) : wxT("")); // Store any mountpt, or delete any previous entry ++#else ++AtMountPt = (IsMounted ? wxString(mnt->f_mntonname, wxConvUTF8) : wxT("")); ++#endif + + if (IsMounted) + MountptCombo->SetValue(AtMountPt); +@@ -1736,6 +1765,7 @@ void UnMountSambaDialog::SearchForNetworkMounts() // + + void UnMountSambaDialog::SearchForNetworkMounts() // Scans mtab for established NFS & samba mounts + { ++#ifdef __linux__ + FILE* fmp = setmntent (_PATH_MOUNTED, "r"); // Get a file* to (probably) /etc/mtab + if (fmp==NULL) return; + +@@ -1749,6 +1779,19 @@ while (1) + { struct PartitionStruct* newmnt = new struct PartitionStruct; + newmnt->device = wxString(mnt->mnt_fsname, wxConvUTF8); + newmnt->mountpt = wxString(mnt->mnt_dir, wxConvUTF8); ++#else ++struct statfs *fslist; ++ ++int numfs = getmntinfo(&fslist, MNT_NOWAIT); ++if (numfs < 1) return; ++ ++for (int i = 0; i < numfs; ++i) ++ { wxString type(fslist[i].f_fstypename, wxConvUTF8); ++ if (ParseNetworkFstype(type) != MT_invalid) ++ { struct PartitionStruct* newmnt = new struct PartitionStruct; ++ newmnt->device = wxString(fslist[i].f_mntfromname, wxConvUTF8); ++ newmnt->mountpt = wxString(fslist[i].f_mntonname, wxConvUTF8); ++#endif + newmnt->type = type; + Mntarray.Add(newmnt); + } diff --git a/x11-fm/4pane/pkg-descr b/x11-fm/4pane/pkg-descr new file mode 100644 index 000000000000..efd1c0290336 --- /dev/null +++ b/x11-fm/4pane/pkg-descr @@ -0,0 +1,6 @@ +4Pane is a multi-pane, detailed-list file manager for Unix-like systems. +It is designed to be fully-featured without bloat, and aims for speed +rather than visual effects. In addition to standard file manager things, +it offers multiple undo and redo of most operations (including deletions), +archive management including "virtual browsing" inside archives, multiple +renaming/duplication of files, terminal emulator, and user-defined tools. diff --git a/x11-fm/4pane/pkg-plist b/x11-fm/4pane/pkg-plist new file mode 100644 index 000000000000..a8a141a5d3ac --- /dev/null +++ b/x11-fm/4pane/pkg-plist @@ -0,0 +1,196 @@ +bin/4Pane +bin/4pane +share/4Pane/bitmaps/4Pane.png +share/4Pane/bitmaps/4PaneIcon16.xpm +share/4Pane/bitmaps/4PaneIcon32.xpm +share/4Pane/bitmaps/4PaneIcon40x32.xpm +share/4Pane/bitmaps/4PaneIcon48.png +share/4Pane/bitmaps/4PaneIcon48.xpm +share/4Pane/bitmaps/DelTab.png +share/4Pane/bitmaps/DnDSelectedCursor.png +share/4Pane/bitmaps/DnDStdCursor.png +share/4Pane/bitmaps/MyDocuments.xpm +share/4Pane/bitmaps/NewTab.png +share/4Pane/bitmaps/Preview.png +share/4Pane/bitmaps/UsbMem.xpm +share/4Pane/bitmaps/UsbMulticard.xpm +share/4Pane/bitmaps/UsbPen.xpm +share/4Pane/bitmaps/abiword.png +share/4Pane/bitmaps/back.xpm +share/4Pane/bitmaps/bm1_button.xpm +share/4Pane/bitmaps/bm2_button.xpm +share/4Pane/bitmaps/bm3_button.xpm +share/4Pane/bitmaps/cdda.png +share/4Pane/bitmaps/cdr.xpm +share/4Pane/bitmaps/cdrom.xpm +share/4Pane/bitmaps/chrome-chromium.png +share/4Pane/bitmaps/clear_right.xpm +share/4Pane/bitmaps/connect_no.xpm +share/4Pane/bitmaps/dir_up.xpm +share/4Pane/bitmaps/down.xpm +share/4Pane/bitmaps/dragicon.png +share/4Pane/bitmaps/evince.xpm +share/4Pane/bitmaps/featherpad.png +share/4Pane/bitmaps/fileopen.xpm +share/4Pane/bitmaps/firefox.png +share/4Pane/bitmaps/floppy.xpm +share/4Pane/bitmaps/forward.xpm +share/4Pane/bitmaps/gedit.xpm +share/4Pane/bitmaps/gjots.png +share/4Pane/bitmaps/gohome.xpm +share/4Pane/bitmaps/gphoto2.png +share/4Pane/bitmaps/harddisk-usb.xpm +share/4Pane/bitmaps/harddisk.xpm +share/4Pane/bitmaps/hardlink.png +share/4Pane/bitmaps/help.png +share/4Pane/bitmaps/iceweasel.png +share/4Pane/bitmaps/kedit.xpm +share/4Pane/bitmaps/kwrite.xpm +share/4Pane/bitmaps/largedropdown.png +share/4Pane/bitmaps/largedropdown.xpm +share/4Pane/bitmaps/libreoffice.png +share/4Pane/bitmaps/mate-text-editor.png +share/4Pane/bitmaps/mousepad.png +share/4Pane/bitmaps/mozillacrystal.png +share/4Pane/bitmaps/mtp.png +share/4Pane/bitmaps/new_dir.xpm +share/4Pane/bitmaps/openoffice.png +share/4Pane/bitmaps/palemoon.png +share/4Pane/bitmaps/photocopier_0.png +share/4Pane/bitmaps/photocopier_1.png +share/4Pane/bitmaps/photocopier_10.png +share/4Pane/bitmaps/photocopier_11.png +share/4Pane/bitmaps/photocopier_12.png +share/4Pane/bitmaps/photocopier_13.png +share/4Pane/bitmaps/photocopier_14.png +share/4Pane/bitmaps/photocopier_15.png +share/4Pane/bitmaps/photocopier_16.png +share/4Pane/bitmaps/photocopier_17.png +share/4Pane/bitmaps/photocopier_18.png +share/4Pane/bitmaps/photocopier_19.png +share/4Pane/bitmaps/photocopier_2.png +share/4Pane/bitmaps/photocopier_20.png +share/4Pane/bitmaps/photocopier_21.png +share/4Pane/bitmaps/photocopier_22.png +share/4Pane/bitmaps/photocopier_23.png +share/4Pane/bitmaps/photocopier_24.png +share/4Pane/bitmaps/photocopier_25.png +share/4Pane/bitmaps/photocopier_26.png +share/4Pane/bitmaps/photocopier_27.png +share/4Pane/bitmaps/photocopier_28.png +share/4Pane/bitmaps/photocopier_29.png +share/4Pane/bitmaps/photocopier_3.png +share/4Pane/bitmaps/photocopier_30.png +share/4Pane/bitmaps/photocopier_31.png +share/4Pane/bitmaps/photocopier_32.png +share/4Pane/bitmaps/photocopier_33.png +share/4Pane/bitmaps/photocopier_34.png +share/4Pane/bitmaps/photocopier_35.png +share/4Pane/bitmaps/photocopier_36.png +share/4Pane/bitmaps/photocopier_37.png +share/4Pane/bitmaps/photocopier_38.png +share/4Pane/bitmaps/photocopier_39.png +share/4Pane/bitmaps/photocopier_4.png +share/4Pane/bitmaps/photocopier_40.png +share/4Pane/bitmaps/photocopier_41.png +share/4Pane/bitmaps/photocopier_42.png +share/4Pane/bitmaps/photocopier_43.png +share/4Pane/bitmaps/photocopier_5.png +share/4Pane/bitmaps/photocopier_6.png +share/4Pane/bitmaps/photocopier_7.png +share/4Pane/bitmaps/photocopier_8.png +share/4Pane/bitmaps/photocopier_9.png +share/4Pane/bitmaps/seamonkey.png +share/4Pane/bitmaps/smalldropdown.png +share/4Pane/bitmaps/smalldropdown.xpm +share/4Pane/bitmaps/softlink.png +share/4Pane/bitmaps/toparent.xpm +share/4Pane/bitmaps/unknown.xpm +share/4Pane/rc/4Pane.desktop +share/4Pane/rc/configuredialogs.xrc +share/4Pane/rc/dialogs.xrc +share/4Pane/rc/moredialogs.xrc +share/doc/4Pane/About.htm +share/doc/4Pane/Archive.htm +share/doc/4Pane/ArchiveBrowse.htm +share/doc/4Pane/Bookmarks.htm +share/doc/4Pane/Chapt.con +share/doc/4Pane/Chapt.hhc +share/doc/4Pane/Chapt.hhk +share/doc/4Pane/Chapt.hhp +share/doc/4Pane/Configure.htm +share/doc/4Pane/ConfigureUserDefTools.htm +share/doc/4Pane/ConfiguringDevices.htm +share/doc/4Pane/ConfiguringDisplay.htm +share/doc/4Pane/ConfiguringMisc.htm +share/doc/4Pane/ConfiguringNetworks.htm +share/doc/4Pane/ConfiguringShortcuts.htm +share/doc/4Pane/ConfiguringTerminals.htm +share/doc/4Pane/Contents.htm +share/doc/4Pane/ContextMenu.htm +share/doc/4Pane/Copier.png +share/doc/4Pane/Devices.htm +share/doc/4Pane/Display.htm +share/doc/4Pane/DnD.htm +share/doc/4Pane/DnDSelectedCursor.png +share/doc/4Pane/DnDStdCursor.png +share/doc/4Pane/Edit.htm +share/doc/4Pane/Editors.htm +share/doc/4Pane/Export.htm +share/doc/4Pane/FAQ.htm +share/doc/4Pane/Features.htm +share/doc/4Pane/FileviewCols.htm +share/doc/4Pane/Filter.htm +share/doc/4Pane/Hardlink.png +share/doc/4Pane/Introduction.htm +share/doc/4Pane/KeyboardNavigation.htm +share/doc/4Pane/Licence.htm +share/doc/4Pane/Menu.htm +share/doc/4Pane/Mount.htm +share/doc/4Pane/Move.png +share/doc/4Pane/MultipleRenDup.htm +share/doc/4Pane/Open.htm +share/doc/4Pane/OpenWith.htm +share/doc/4Pane/Options.htm +share/doc/4Pane/Previews.htm +share/doc/4Pane/Properties.htm +share/doc/4Pane/Quickstart.htm +share/doc/4Pane/RAQ.htm +share/doc/4Pane/RegExpHelp.htm +share/doc/4Pane/Running.htm +share/doc/4Pane/Softlink.png +share/doc/4Pane/Statusbar.htm +share/doc/4Pane/Tabs.htm +share/doc/4Pane/TerminalEm.htm +share/doc/4Pane/Toolbar.htm +share/doc/4Pane/Tools.htm +share/doc/4Pane/UnRedo.htm +share/doc/4Pane/Using4Pane.htm +share/doc/4Pane/View.htm +share/doc/4Pane/back.gif +share/doc/4Pane/forward.gif +share/doc/4Pane/up.gif +share/icons/hicolor/48x48/apps/4Pane.png +share/icons/hicolor/scalable/apps/4Pane.svg +%%NLS%%share/locale/ar/LC_MESSAGES/4Pane.mo +%%NLS%%share/locale/ca/LC_MESSAGES/4Pane.mo +%%NLS%%share/locale/da/LC_MESSAGES/4Pane.mo +%%NLS%%share/locale/de/LC_MESSAGES/4Pane.mo +%%NLS%%share/locale/el/LC_MESSAGES/4Pane.mo +%%NLS%%share/locale/es/LC_MESSAGES/4Pane.mo +%%NLS%%share/locale/et/LC_MESSAGES/4Pane.mo +%%NLS%%share/locale/fa/LC_MESSAGES/4Pane.mo +%%NLS%%share/locale/fi_FI/LC_MESSAGES/4Pane.mo +%%NLS%%share/locale/fr/LC_MESSAGES/4Pane.mo +%%NLS%%share/locale/fr_FR/LC_MESSAGES/4Pane.mo +%%NLS%%share/locale/it/LC_MESSAGES/4Pane.mo +%%NLS%%share/locale/ja/LC_MESSAGES/4Pane.mo +%%NLS%%share/locale/nl/LC_MESSAGES/4Pane.mo +%%NLS%%share/locale/pl/LC_MESSAGES/4Pane.mo +%%NLS%%share/locale/pt_BR/LC_MESSAGES/4Pane.mo +%%NLS%%share/locale/ru/LC_MESSAGES/4Pane.mo +%%NLS%%share/locale/tr/LC_MESSAGES/4Pane.mo +%%NLS%%share/locale/uk_UA/LC_MESSAGES/4Pane.mo +%%NLS%%share/locale/vi/LC_MESSAGES/4Pane.mo +%%NLS%%share/locale/zh_CN/LC_MESSAGES/4Pane.mo +share/metainfo/4Pane.appdata.xml diff --git a/x11-fm/Makefile b/x11-fm/Makefile index d83874fd104e..2520a9d95326 100644 --- a/x11-fm/Makefile +++ b/x11-fm/Makefile @@ -1,5 +1,6 @@ COMMENT = X11 file managers + SUBDIR += 4pane SUBDIR += arqiver SUBDIR += caja SUBDIR += catseye-fm