From 26706a11c2def748a90a93b0c0cf002df8063fcc Mon Sep 17 00:00:00 2001 From: Laszlo Magyar Date: Mon, 10 Jun 2024 22:14:46 +0200 Subject: [PATCH 01/19] fix Android bug on FAT32 time resolution and mtime caching --- .../org/primftpd/filesystem/SafSshFile.java | 12 ++++++ .../filesystem/SafSshFileSystemView.java | 6 +++ .../filesystem/StorageManagerUtil.java | 41 +++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafSshFile.java b/primitiveFTPd/src/org/primftpd/filesystem/SafSshFile.java index 7d2de931..1ae8a095 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafSshFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafSshFile.java @@ -56,6 +56,18 @@ public String getClientIp() { return SshUtils.getClientIp(session); } + @Override + public boolean setLastModified(long time) { + int timeResolution = fileSystemView.getTimeResolution(); + long convertedTime; + if (timeResolution != 1000) { // in case of sftp, this is the finest resolution + convertedTime = (time / timeResolution) * timeResolution; + } else { + convertedTime = time; + } + return super.setLastModified(convertedTime); + } + @Override public boolean move(SshFile target) { logger.trace("move()"); diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafSshFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/SafSshFileSystemView.java index 5fab924b..4321852f 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafSshFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafSshFileSystemView.java @@ -13,12 +13,18 @@ public class SafSshFileSystemView extends SafFileSystemView implements FileSystemView { private final Session session; + private final int timeResolution; public SafSshFileSystemView(Context context, Uri startUrl, ContentResolver contentResolver, PftpdService pftpdService, Session session) { super(context, startUrl, contentResolver, pftpdService); this.session = session; + timeResolution = StorageManagerUtil.getFilesystemTimeResolutionForSftp(startUrl); } + protected int getTimeResolution() { + return timeResolution; + } + @Override protected SafSshFile createFile( ContentResolver contentResolver, diff --git a/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java b/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java index f5122d20..271f0ed7 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java @@ -11,14 +11,21 @@ import androidx.annotation.Nullable; import androidx.documentfile.provider.DocumentFile; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; +import java.io.FileReader; import java.lang.reflect.Array; import java.lang.reflect.Method; public final class StorageManagerUtil { private static final String PRIMARY_VOLUME_NAME = "primary"; + private static Logger logger = LoggerFactory.getLogger(StorageManagerUtil.class); + public static String getFullDocIdPathFromTreeUri(@Nullable final Uri treeUri, Context context) { if (treeUri == null) { return null; @@ -47,6 +54,40 @@ public static String getFullDocIdPathFromTreeUri(@Nullable final Uri treeUri, Co } } + public static int getFilesystemTimeResolutionForSftp(Uri startUrl) { + logger.trace("getFilesystemTimeResolutionForSftp({})", startUrl); + String mountPoint = "/mnt/media_rw/" + getVolumeIdFromTreeUri(startUrl); + try(BufferedReader br = new BufferedReader(new FileReader("/proc/mounts"))) { + // sample contents for /proc/mounts + // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX vfat ... 0 0 + // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX sdfat ...,fs=exfat,... 0 0 + // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX sdfat ...,fs=vfat:32,... 0 0 + for (String line; (line = br.readLine()) != null; ) { + String[] mountInformations = line.split(" "); + if (mountInformations.length >= 4 && mountInformations[1].equals(mountPoint)) { + if (mountInformations[2].equals("vfat")) { + logger.trace(" found mount point {} with type {}", mountInformations[1], mountInformations[2]); + return 2000; + } else if (mountInformations[2].equals("sdfat")) { + for (String option : mountInformations[3].split(",")) { + if (option.startsWith("fs=")) { + if (option.startsWith("fs=vfat")) { + logger.trace(" found mount point {} with type {} with option {}", new Object[]{mountInformations[1], mountInformations[2], option}); + return 2000; + } + break; + } + } + } + break; + } + } + } catch (Exception e) { + logger.error("getFilesystemTimeResolutionForSftp() {}", e); + } + return 1000; // in case of sftp, this is the finest resolution + } + @SuppressLint("ObsoleteSdkInt") private static String getVolumePath(final String volumeId, Context context) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { From 59702d3b82f362179559c490a1ceaafbb3818fc4 Mon Sep 17 00:00:00 2001 From: Laszlo Magyar Date: Tue, 11 Jun 2024 01:03:25 +0200 Subject: [PATCH 02/19] move fileSystemView up in the hierarchy --- .../src/org/primftpd/filesystem/SafFile.java | 18 +++++++--- .../filesystem/SafFileSystemView.java | 12 +++++-- .../org/primftpd/filesystem/SafFtpFile.java | 11 +++--- .../filesystem/SafFtpFileSystemView.java | 10 +++--- .../org/primftpd/filesystem/SafSshFile.java | 34 ++++++------------- .../filesystem/SafSshFileSystemView.java | 15 ++++---- .../filesystem/StorageManagerUtil.java | 22 +++++++----- 7 files changed, 67 insertions(+), 55 deletions(-) diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java b/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java index 23c06a2f..29c705a0 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java @@ -40,6 +40,7 @@ public abstract class SafFile extends AbstractFile { private DocumentFile documentFile; private final DocumentFile parentDocumentFile; + protected final SafFileSystemView fileSystemView; private boolean writable; @@ -48,7 +49,8 @@ public SafFile( DocumentFile parentDocumentFile, DocumentFile documentFile, String absPath, - PftpdService pftpdService) { + PftpdService pftpdService, + SafFileSystemView fileSystemView) { // this c-tor is to be used to access existing files super( absPath, @@ -65,6 +67,7 @@ public SafFile( this.parentDocumentFile = parentDocumentFile; this.documentFile = documentFile; + this.fileSystemView = fileSystemView; name = documentFile.getName(); if (name == null && SafFileSystemView.ROOT_PATH.equals(absPath)) { @@ -78,7 +81,8 @@ public SafFile( DocumentFile parentDocumentFile, String name, String absPath, - PftpdService pftpdService) { + PftpdService pftpdService, + SafFileSystemView fileSystemView) { // this c-tor is to be used to upload new files, create directories or renaming super(absPath, name, 0, 0, false, false, false, pftpdService); String parentName = parentDocumentFile.getName(); @@ -89,6 +93,7 @@ public SafFile( this.writable = true; this.parentDocumentFile = parentDocumentFile; + this.fileSystemView = fileSystemView; } protected abstract T createFile( @@ -96,7 +101,8 @@ protected abstract T createFile( DocumentFile parentDocumentFile, DocumentFile documentFile, String absPath, - PftpdService pftpdService); + PftpdService pftpdService, + SafFileSystemView fileSystemView); @Override public ClientActionEvent.Storage getClientActionStorage() { @@ -127,7 +133,9 @@ public boolean setLastModified(long time) { try { Uri docUri = documentFile.getUri(); Path filePath = Paths.get(StorageManagerUtil.getFullDocIdPathFromTreeUri(docUri, pftpdService.getContext())); - Files.getFileAttributeView(filePath, BasicFileAttributeView.class).setTimes(FileTime.fromMillis(time), null, null); + int timeResolution = fileSystemView.getTimeResolution(); + long convertedTime = (time / timeResolution) * timeResolution; + Files.getFileAttributeView(filePath, BasicFileAttributeView.class).setTimes(FileTime.fromMillis(convertedTime), null, null); } catch (Exception e) { String baseMsg = "could not set last modified time"; logger.error(baseMsg, e); @@ -180,7 +188,7 @@ public List listFiles() { String absPath = this.absPath.endsWith("/") ? this.absPath + child.getName() : this.absPath + "/" + child.getName(); - result.add(createFile(contentResolver, documentFile, child, absPath, pftpdService)); + result.add(createFile(contentResolver, documentFile, child, absPath, pftpdService, fileSystemView)); } logger.trace(" [{}] listFiles(): num children: {}", name, Integer.valueOf(result.size())); return result; diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/SafFileSystemView.java index bfddd20b..91cb7115 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafFileSystemView.java @@ -25,12 +25,18 @@ public abstract class SafFileSystemView, X> { protected final Uri startUrl; protected final ContentResolver contentResolver; protected final PftpdService pftpdService; + protected final int timeResolution; public SafFileSystemView(Context context, Uri startUrl, ContentResolver contentResolver, PftpdService pftpdService) { this.context = context; this.startUrl = startUrl; this.contentResolver = contentResolver; this.pftpdService = pftpdService; + timeResolution = StorageManagerUtil.getFilesystemTimeResolutionForTreeUri(startUrl); + } + + protected int getTimeResolution() { + return timeResolution; } protected abstract T createFile( @@ -38,13 +44,15 @@ protected abstract T createFile( DocumentFile parentDocumentFile, DocumentFile documentFile, String absPath, - PftpdService pftpdService); + PftpdService pftpdService, + SafFileSystemView fileSystemView); protected abstract T createFile( ContentResolver contentResolver, DocumentFile parentDocumentFile, String name, String absPath, - PftpdService pftpdService); + PftpdService pftpdService, + SafFileSystemView fileSystemView); protected abstract String absolute(String file); diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFile.java b/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFile.java index bb83bc30..d3cd222b 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFile.java @@ -17,8 +17,9 @@ public SafFtpFile( DocumentFile documentFile, String absPath, PftpdService pftpdService, + SafFileSystemView fileSystemView, User user) { - super(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService); + super(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, fileSystemView); this.user = user; } @@ -28,8 +29,9 @@ public SafFtpFile( String name, String absPath, PftpdService pftpdService, + SafFileSystemView fileSystemView, User user) { - super(contentResolver, parentDocumentFile, name, absPath, pftpdService); + super(contentResolver, parentDocumentFile, name, absPath, pftpdService, fileSystemView); this.user = user; } @@ -39,8 +41,9 @@ protected FtpFile createFile( DocumentFile parentDocumentFile, DocumentFile documentFile, String absPath, - PftpdService pftpdService) { - return new SafFtpFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, user); + PftpdService pftpdService, + SafFileSystemView fileSystemView) { + return new SafFtpFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, fileSystemView, user); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFileSystemView.java index 09b3d8bc..595600ce 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFileSystemView.java @@ -28,9 +28,10 @@ protected SafFtpFile createFile( DocumentFile parentDocumentFile, DocumentFile documentFile, String absPath, - PftpdService pftpdService) { + PftpdService pftpdService, + SafFileSystemView fileSystemView) { logger.trace("createFile(DocumentFile)"); - return new SafFtpFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, user); + return new SafFtpFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, fileSystemView, user); } @Override @@ -39,9 +40,10 @@ protected SafFtpFile createFile( DocumentFile parentDocumentFile, String name, String absPath, - PftpdService pftpdService) { + PftpdService pftpdService, + SafFileSystemView fileSystemView) { logger.trace("createFile(String)"); - return new SafFtpFile(contentResolver, parentDocumentFile, name, absPath, pftpdService, user); + return new SafFtpFile(contentResolver, parentDocumentFile, name, absPath, pftpdService, fileSystemView, user); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafSshFile.java b/primitiveFTPd/src/org/primftpd/filesystem/SafSshFile.java index 1ae8a095..76891791 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafSshFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafSshFile.java @@ -13,7 +13,6 @@ public class SafSshFile extends SafFile implements SshFile { private final Session session; - private final SafSshFileSystemView fileSystemView; public SafSshFile( ContentResolver contentResolver, @@ -21,11 +20,10 @@ public SafSshFile( DocumentFile documentFile, String absPath, PftpdService pftpdService, - Session session, - SafSshFileSystemView fileSystemView) { - super(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService); + SafFileSystemView fileSystemView, + Session session) { + super(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, fileSystemView); this.session = session; - this.fileSystemView = fileSystemView; } public SafSshFile( @@ -34,11 +32,10 @@ public SafSshFile( String name, String absPath, PftpdService pftpdService, - Session session, - SafSshFileSystemView fileSystemView) { - super(contentResolver, parentDocumentFile, name, absPath, pftpdService); + SafFileSystemView fileSystemView, + Session session) { + super(contentResolver, parentDocumentFile, name, absPath, pftpdService, fileSystemView); this.session = session; - this.fileSystemView = fileSystemView; } @Override @@ -47,8 +44,9 @@ protected SshFile createFile( DocumentFile parentDocumentFile, DocumentFile documentFile, String absPath, - PftpdService pftpdService) { - return new SafSshFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, session, fileSystemView); + PftpdService pftpdService, + SafFileSystemView fileSystemView) { + return new SafSshFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, fileSystemView, session); } @Override @@ -56,18 +54,6 @@ public String getClientIp() { return SshUtils.getClientIp(session); } - @Override - public boolean setLastModified(long time) { - int timeResolution = fileSystemView.getTimeResolution(); - long convertedTime; - if (timeResolution != 1000) { // in case of sftp, this is the finest resolution - convertedTime = (time / timeResolution) * timeResolution; - } else { - convertedTime = time; - } - return super.setLastModified(convertedTime); - } - @Override public boolean move(SshFile target) { logger.trace("move()"); @@ -98,7 +84,7 @@ public SshFile getParentFile() { parentPath = "/"; } logger.trace("[{}] getParentFile() -> {}", name, parentPath); - return fileSystemView.getFile(parentPath); + return (SshFile)fileSystemView.getFile(parentPath); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafSshFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/SafSshFileSystemView.java index 4321852f..d80dfd40 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafSshFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafSshFileSystemView.java @@ -13,16 +13,15 @@ public class SafSshFileSystemView extends SafFileSystemView implements FileSystemView { private final Session session; - private final int timeResolution; public SafSshFileSystemView(Context context, Uri startUrl, ContentResolver contentResolver, PftpdService pftpdService, Session session) { super(context, startUrl, contentResolver, pftpdService); this.session = session; - timeResolution = StorageManagerUtil.getFilesystemTimeResolutionForSftp(startUrl); } + @Override protected int getTimeResolution() { - return timeResolution; + return timeResolution > 1000 ? timeResolution : 1000; // sftp messages have 1s resolution } @Override @@ -31,8 +30,9 @@ protected SafSshFile createFile( DocumentFile parentDocumentFile, DocumentFile documentFile, String absPath, - PftpdService pftpdService) { - return new SafSshFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, session, this); + PftpdService pftpdService, + SafFileSystemView fileSystemView) { + return new SafSshFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, fileSystemView, session); } @Override @@ -41,8 +41,9 @@ protected SafSshFile createFile( DocumentFile parentDocumentFile, String name, String absPath, - PftpdService pftpdService) { - return new SafSshFile(contentResolver, parentDocumentFile, name, absPath, pftpdService, session, this); + PftpdService pftpdService, + SafFileSystemView fileSystemView) { + return new SafSshFile(contentResolver, parentDocumentFile, name, absPath, pftpdService, fileSystemView, session); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java b/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java index 271f0ed7..6692a7cc 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java @@ -54,26 +54,30 @@ public static String getFullDocIdPathFromTreeUri(@Nullable final Uri treeUri, Co } } - public static int getFilesystemTimeResolutionForSftp(Uri startUrl) { - logger.trace("getFilesystemTimeResolutionForSftp({})", startUrl); + public static int getFilesystemTimeResolutionForTreeUri(Uri startUrl) { + logger.trace("getFilesystemTimeResolutionForTreeUri({})", startUrl); String mountPoint = "/mnt/media_rw/" + getVolumeIdFromTreeUri(startUrl); try(BufferedReader br = new BufferedReader(new FileReader("/proc/mounts"))) { // sample contents for /proc/mounts - // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX vfat ... 0 0 - // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX sdfat ...,fs=exfat,... 0 0 - // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX sdfat ...,fs=vfat:32,... 0 0 + // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX vfat ... 0 0 -> 2000 ms + // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX sdfat ...,fs=vfat:16,... 0 0 -> 2000 ms + // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX sdfat ...,fs=vfat:32,... 0 0 -> 2000 ms + // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX sdfat ...,fs=exfat,... 0 0 -> 10 ms for (String line; (line = br.readLine()) != null; ) { String[] mountInformations = line.split(" "); if (mountInformations.length >= 4 && mountInformations[1].equals(mountPoint)) { if (mountInformations[2].equals("vfat")) { - logger.trace(" found mount point {} with type {}", mountInformations[1], mountInformations[2]); + logger.trace(" found mount point {} with type {} -> 2000ms", mountInformations[1], mountInformations[2]); return 2000; } else if (mountInformations[2].equals("sdfat")) { for (String option : mountInformations[3].split(",")) { if (option.startsWith("fs=")) { if (option.startsWith("fs=vfat")) { - logger.trace(" found mount point {} with type {} with option {}", new Object[]{mountInformations[1], mountInformations[2], option}); + logger.trace(" found mount point {} with type {} with option {} -> 2000ms", new Object[]{mountInformations[1], mountInformations[2], option}); return 2000; + } else if (option.startsWith("fs=exfat")) { + logger.trace(" found mount point {} with type {} with option {} -> 10ms", new Object[]{mountInformations[1], mountInformations[2], option}); + return 10; } break; } @@ -83,9 +87,9 @@ public static int getFilesystemTimeResolutionForSftp(Uri startUrl) { } } } catch (Exception e) { - logger.error("getFilesystemTimeResolutionForSftp() {}", e); + logger.error("getFilesystemTimeResolutionForTreeUri() {}", e); } - return 1000; // in case of sftp, this is the finest resolution + return 1; // we don't know, assume 1ms } @SuppressLint("ObsoleteSdkInt") From d58d9d6b736af46b15b609c37ac76a8d65fab097 Mon Sep 17 00:00:00 2001 From: Laszlo Magyar Date: Wed, 11 Sep 2024 22:50:25 +0200 Subject: [PATCH 03/19] workaround for sdcardfs over sdfat/exfat, still 2000ms resolution not 10ms --- .../filesystem/StorageManagerUtil.java | 67 ++++++++++++++----- 1 file changed, 49 insertions(+), 18 deletions(-) diff --git a/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java b/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java index 6692a7cc..5b4e7c59 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java @@ -54,42 +54,73 @@ public static String getFullDocIdPathFromTreeUri(@Nullable final Uri treeUri, Co } } + // This function is to handle 2 Android bugs: + // 1. Android caches the modification times for files, ie. when we read back the modification time of a freshly created file, + // Andorid will lie and return the value the file was asked to be saved, and not the value the real file-system was able to store, + // so we have to figure out whether the underlying file-system is an SD-card related and use the file-system specific resolution. + // 2. Even when the SD-card is mounted at /mnt/media_rw/XXXX-XXXX with the proper file-system, when it is mounted at /storage/XXXX-XXXX, + // the used sdcardfs has another bug, it provides the same 2s resolution even for the exfat file-system, + // so in this case we have to modify the resolution even for the exfat file-system to 2s. public static int getFilesystemTimeResolutionForTreeUri(Uri startUrl) { logger.trace("getFilesystemTimeResolutionForTreeUri({})", startUrl); - String mountPoint = "/mnt/media_rw/" + getVolumeIdFromTreeUri(startUrl); + int mediaTimeResolution = 0; + int storageTimeResolution = 0; + String volumeId = getVolumeIdFromTreeUri(startUrl); + String mediaMountPoint = "/mnt/media_rw/" + volumeId; + String mediaOption = null; + String storageMountPoint = "/storage/" + volumeId; try(BufferedReader br = new BufferedReader(new FileReader("/proc/mounts"))) { // sample contents for /proc/mounts // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX vfat ... 0 0 -> 2000 ms // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX sdfat ...,fs=vfat:16,... 0 0 -> 2000 ms // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX sdfat ...,fs=vfat:32,... 0 0 -> 2000 ms // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX sdfat ...,fs=exfat,... 0 0 -> 10 ms + // /mnt/media_rw/XXXX-XXXX /storage/XXXX-XXXX sdcardfs ... 0 0 -> 2000 ms for (String line; (line = br.readLine()) != null; ) { String[] mountInformations = line.split(" "); - if (mountInformations.length >= 4 && mountInformations[1].equals(mountPoint)) { - if (mountInformations[2].equals("vfat")) { - logger.trace(" found mount point {} with type {} -> 2000ms", mountInformations[1], mountInformations[2]); - return 2000; - } else if (mountInformations[2].equals("sdfat")) { - for (String option : mountInformations[3].split(",")) { - if (option.startsWith("fs=")) { - if (option.startsWith("fs=vfat")) { - logger.trace(" found mount point {} with type {} with option {} -> 2000ms", new Object[]{mountInformations[1], mountInformations[2], option}); - return 2000; - } else if (option.startsWith("fs=exfat")) { - logger.trace(" found mount point {} with type {} with option {} -> 10ms", new Object[]{mountInformations[1], mountInformations[2], option}); - return 10; + if (mountInformations.length >= 4) { + if (mediaTimeResolution == 0 && mountInformations[1].equals(mediaMountPoint)) { + if (mountInformations[2].equals("vfat")) { + mediaTimeResolution = 2000; + } else if (mountInformations[2].equals("sdfat")) { + mediaTimeResolution = 2000; // use 2000ms by default + for (String option : mountInformations[3].split(",")) { + if (option.startsWith("fs=")) { + mediaOption = option; + if (option.startsWith("fs=vfat")) { + mediaTimeResolution = 2000; + } else if (option.startsWith("fs=exfat")) { + mediaTimeResolution = 10; + } + break; } - break; } + } else { + mediaTimeResolution = 1; } + if (mediaOption == null) { + logger.trace(" found media mount point {} with type {} -> {}ms", new Object[]{mountInformations[1], mountInformations[2], mediaTimeResolution}); + } else { + logger.trace(" found media mount point {} with type {} with option {} -> {}ms", new Object[]{mountInformations[1], mountInformations[2], mediaOption, mediaTimeResolution}); + } + } + if (storageTimeResolution == 0 && mountInformations[1].equals(storageMountPoint)) { + if (mountInformations[2].equals("sdcardfs")) { + storageTimeResolution = 2000; + } else { + storageTimeResolution = 1; + } + logger.trace(" found storage mount point {} with type {} -> {}ms", new Object[]{mountInformations[1], mountInformations[2], storageTimeResolution}); + } + if (mediaTimeResolution != 0 && storageTimeResolution != 0) { + break; } - break; } } } catch (Exception e) { logger.error("getFilesystemTimeResolutionForTreeUri() {}", e); } - return 1; // we don't know, assume 1ms + return Math.max(1, Math.max(mediaTimeResolution, storageTimeResolution)); // use 1ms by default } @SuppressLint("ObsoleteSdkInt") @@ -140,7 +171,7 @@ public static String getVolumeIdFromTreeUri(final Uri treeUri) { } } - @TargetApi(Build.VERSION_CODES.LOLLIPOP) + @TargetApi(Build.VERSION_CODES.LOLLIPOP) private static String getDocumentPathFromTreeUri(final Uri treeUri) { final String docId = DocumentsContract.getDocumentId(treeUri); final String[] split = docId.split(":"); From 722aa6c9fc027a1b46340b71726f40814e844d0d Mon Sep 17 00:00:00 2001 From: Laszlo Magyar Date: Thu, 26 Sep 2024 16:47:44 +0200 Subject: [PATCH 04/19] refactor timeResolution --- .../src/org/primftpd/filesystem/SafFile.java | 16 ++++------ .../filesystem/SafFileSystemView.java | 12 ++----- .../org/primftpd/filesystem/SafFtpFile.java | 13 ++++---- .../filesystem/SafFtpFileSystemView.java | 10 +++--- .../org/primftpd/filesystem/SafSshFile.java | 24 ++++++++------ .../filesystem/SafSshFileSystemView.java | 15 +++------ .../filesystem/StorageManagerUtil.java | 32 ++++++++++++------- 7 files changed, 59 insertions(+), 63 deletions(-) diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java b/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java index 29c705a0..58a76a12 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java @@ -40,7 +40,7 @@ public abstract class SafFile extends AbstractFile { private DocumentFile documentFile; private final DocumentFile parentDocumentFile; - protected final SafFileSystemView fileSystemView; + protected final int timeResolution; private boolean writable; @@ -50,7 +50,7 @@ public SafFile( DocumentFile documentFile, String absPath, PftpdService pftpdService, - SafFileSystemView fileSystemView) { + int timeResolution) { // this c-tor is to be used to access existing files super( absPath, @@ -67,7 +67,7 @@ public SafFile( this.parentDocumentFile = parentDocumentFile; this.documentFile = documentFile; - this.fileSystemView = fileSystemView; + this.timeResolution = timeResolution; name = documentFile.getName(); if (name == null && SafFileSystemView.ROOT_PATH.equals(absPath)) { @@ -82,7 +82,7 @@ public SafFile( String name, String absPath, PftpdService pftpdService, - SafFileSystemView fileSystemView) { + int timeResolution) { // this c-tor is to be used to upload new files, create directories or renaming super(absPath, name, 0, 0, false, false, false, pftpdService); String parentName = parentDocumentFile.getName(); @@ -93,7 +93,7 @@ public SafFile( this.writable = true; this.parentDocumentFile = parentDocumentFile; - this.fileSystemView = fileSystemView; + this.timeResolution = timeResolution; } protected abstract T createFile( @@ -101,8 +101,7 @@ protected abstract T createFile( DocumentFile parentDocumentFile, DocumentFile documentFile, String absPath, - PftpdService pftpdService, - SafFileSystemView fileSystemView); + PftpdService pftpdService); @Override public ClientActionEvent.Storage getClientActionStorage() { @@ -133,7 +132,6 @@ public boolean setLastModified(long time) { try { Uri docUri = documentFile.getUri(); Path filePath = Paths.get(StorageManagerUtil.getFullDocIdPathFromTreeUri(docUri, pftpdService.getContext())); - int timeResolution = fileSystemView.getTimeResolution(); long convertedTime = (time / timeResolution) * timeResolution; Files.getFileAttributeView(filePath, BasicFileAttributeView.class).setTimes(FileTime.fromMillis(convertedTime), null, null); } catch (Exception e) { @@ -188,7 +186,7 @@ public List listFiles() { String absPath = this.absPath.endsWith("/") ? this.absPath + child.getName() : this.absPath + "/" + child.getName(); - result.add(createFile(contentResolver, documentFile, child, absPath, pftpdService, fileSystemView)); + result.add(createFile(contentResolver, documentFile, child, absPath, pftpdService)); } logger.trace(" [{}] listFiles(): num children: {}", name, Integer.valueOf(result.size())); return result; diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/SafFileSystemView.java index 91cb7115..39cd163c 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafFileSystemView.java @@ -32,11 +32,7 @@ public SafFileSystemView(Context context, Uri startUrl, ContentResolver contentR this.startUrl = startUrl; this.contentResolver = contentResolver; this.pftpdService = pftpdService; - timeResolution = StorageManagerUtil.getFilesystemTimeResolutionForTreeUri(startUrl); - } - - protected int getTimeResolution() { - return timeResolution; + this.timeResolution = StorageManagerUtil.getFilesystemTimeResolutionForTreeUri(startUrl); } protected abstract T createFile( @@ -44,15 +40,13 @@ protected abstract T createFile( DocumentFile parentDocumentFile, DocumentFile documentFile, String absPath, - PftpdService pftpdService, - SafFileSystemView fileSystemView); + PftpdService pftpdService); protected abstract T createFile( ContentResolver contentResolver, DocumentFile parentDocumentFile, String name, String absPath, - PftpdService pftpdService, - SafFileSystemView fileSystemView); + PftpdService pftpdService); protected abstract String absolute(String file); diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFile.java b/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFile.java index d3cd222b..cc5ffca6 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFile.java @@ -17,9 +17,9 @@ public SafFtpFile( DocumentFile documentFile, String absPath, PftpdService pftpdService, - SafFileSystemView fileSystemView, + int timeResolution, User user) { - super(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, fileSystemView); + super(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, timeResolution); this.user = user; } @@ -29,9 +29,9 @@ public SafFtpFile( String name, String absPath, PftpdService pftpdService, - SafFileSystemView fileSystemView, + int timeResolution, User user) { - super(contentResolver, parentDocumentFile, name, absPath, pftpdService, fileSystemView); + super(contentResolver, parentDocumentFile, name, absPath, pftpdService, timeResolution); this.user = user; } @@ -41,9 +41,8 @@ protected FtpFile createFile( DocumentFile parentDocumentFile, DocumentFile documentFile, String absPath, - PftpdService pftpdService, - SafFileSystemView fileSystemView) { - return new SafFtpFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, fileSystemView, user); + PftpdService pftpdService) { + return new SafFtpFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, timeResolution, user); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFileSystemView.java index 595600ce..a57a8bd8 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFileSystemView.java @@ -28,10 +28,9 @@ protected SafFtpFile createFile( DocumentFile parentDocumentFile, DocumentFile documentFile, String absPath, - PftpdService pftpdService, - SafFileSystemView fileSystemView) { + PftpdService pftpdService) { logger.trace("createFile(DocumentFile)"); - return new SafFtpFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, fileSystemView, user); + return new SafFtpFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, timeResolution, user); } @Override @@ -40,10 +39,9 @@ protected SafFtpFile createFile( DocumentFile parentDocumentFile, String name, String absPath, - PftpdService pftpdService, - SafFileSystemView fileSystemView) { + PftpdService pftpdService) { logger.trace("createFile(String)"); - return new SafFtpFile(contentResolver, parentDocumentFile, name, absPath, pftpdService, fileSystemView, user); + return new SafFtpFile(contentResolver, parentDocumentFile, name, absPath, pftpdService, timeResolution, user); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafSshFile.java b/primitiveFTPd/src/org/primftpd/filesystem/SafSshFile.java index 76891791..ca7777ed 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafSshFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafSshFile.java @@ -13,6 +13,7 @@ public class SafSshFile extends SafFile implements SshFile { private final Session session; + private final SafSshFileSystemView fileSystemView; public SafSshFile( ContentResolver contentResolver, @@ -20,10 +21,12 @@ public SafSshFile( DocumentFile documentFile, String absPath, PftpdService pftpdService, - SafFileSystemView fileSystemView, - Session session) { - super(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, fileSystemView); + int timeResolution, + Session session, + SafSshFileSystemView fileSystemView) { + super(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, timeResolution); this.session = session; + this.fileSystemView = fileSystemView; } public SafSshFile( @@ -32,10 +35,12 @@ public SafSshFile( String name, String absPath, PftpdService pftpdService, - SafFileSystemView fileSystemView, - Session session) { - super(contentResolver, parentDocumentFile, name, absPath, pftpdService, fileSystemView); + int timeResolution, + Session session, + SafSshFileSystemView fileSystemView) { + super(contentResolver, parentDocumentFile, name, absPath, pftpdService, timeResolution); this.session = session; + this.fileSystemView = fileSystemView; } @Override @@ -44,9 +49,8 @@ protected SshFile createFile( DocumentFile parentDocumentFile, DocumentFile documentFile, String absPath, - PftpdService pftpdService, - SafFileSystemView fileSystemView) { - return new SafSshFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, fileSystemView, session); + PftpdService pftpdService) { + return new SafSshFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, timeResolution, session, fileSystemView); } @Override @@ -84,7 +88,7 @@ public SshFile getParentFile() { parentPath = "/"; } logger.trace("[{}] getParentFile() -> {}", name, parentPath); - return (SshFile)fileSystemView.getFile(parentPath); + return fileSystemView.getFile(parentPath); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafSshFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/SafSshFileSystemView.java index d80dfd40..7a93df61 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafSshFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafSshFileSystemView.java @@ -19,20 +19,14 @@ public SafSshFileSystemView(Context context, Uri startUrl, ContentResolver conte this.session = session; } - @Override - protected int getTimeResolution() { - return timeResolution > 1000 ? timeResolution : 1000; // sftp messages have 1s resolution - } - @Override protected SafSshFile createFile( ContentResolver contentResolver, DocumentFile parentDocumentFile, DocumentFile documentFile, String absPath, - PftpdService pftpdService, - SafFileSystemView fileSystemView) { - return new SafSshFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, fileSystemView, session); + PftpdService pftpdService) { + return new SafSshFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, timeResolution, session, this); } @Override @@ -41,9 +35,8 @@ protected SafSshFile createFile( DocumentFile parentDocumentFile, String name, String absPath, - PftpdService pftpdService, - SafFileSystemView fileSystemView) { - return new SafSshFile(contentResolver, parentDocumentFile, name, absPath, pftpdService, fileSystemView, session); + PftpdService pftpdService) { + return new SafSshFile(contentResolver, parentDocumentFile, name, absPath, pftpdService, timeResolution, session, this); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java b/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java index 5b4e7c59..4bb49636 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java @@ -54,13 +54,20 @@ public static String getFullDocIdPathFromTreeUri(@Nullable final Uri treeUri, Co } } - // This function is to handle 2 Android bugs: - // 1. Android caches the modification times for files, ie. when we read back the modification time of a freshly created file, - // Andorid will lie and return the value the file was asked to be saved, and not the value the real file-system was able to store, - // so we have to figure out whether the underlying file-system is an SD-card related and use the file-system specific resolution. - // 2. Even when the SD-card is mounted at /mnt/media_rw/XXXX-XXXX with the proper file-system, when it is mounted at /storage/XXXX-XXXX, - // the used sdcardfs has another bug, it provides the same 2s resolution even for the exfat file-system, - // so in this case we have to modify the resolution even for the exfat file-system to 2s. + /** + * This function is to handle 2 Android bugs. + *

+ * 1. Android caches the modification times for files, ie. when we read back the modification time of a freshly created file, + * Andorid will lie and return the value the file was asked to be saved, and not the value the real file-system was able to store, + * so we have to figure out whether the underlying file-system is an SD-card related and use the file-system specific resolution. + *

+ * 2. Even when the SD-card is mounted at /mnt/media_rw/XXXX-XXXX with the proper file-system, when it is mounted at /storage/XXXX-XXXX, + * the used sdcardfs has another bug, it provides the same 2s resolution even for the exfat file-system, + * so in this case we have to modify the resolution even for the exfat file-system to 2s. + * + * @param startUrl SAF startUrl + * @return SAF file system's time resolution measured in milliseconds + */ public static int getFilesystemTimeResolutionForTreeUri(Uri startUrl) { logger.trace("getFilesystemTimeResolutionForTreeUri({})", startUrl); int mediaTimeResolution = 0; @@ -77,6 +84,7 @@ public static int getFilesystemTimeResolutionForTreeUri(Uri startUrl) { // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX sdfat ...,fs=exfat,... 0 0 -> 10 ms // /mnt/media_rw/XXXX-XXXX /storage/XXXX-XXXX sdcardfs ... 0 0 -> 2000 ms for (String line; (line = br.readLine()) != null; ) { + logger.trace(" {}", line); String[] mountInformations = line.split(" "); if (mountInformations.length >= 4) { if (mediaTimeResolution == 0 && mountInformations[1].equals(mediaMountPoint)) { @@ -99,9 +107,9 @@ public static int getFilesystemTimeResolutionForTreeUri(Uri startUrl) { mediaTimeResolution = 1; } if (mediaOption == null) { - logger.trace(" found media mount point {} with type {} -> {}ms", new Object[]{mountInformations[1], mountInformations[2], mediaTimeResolution}); + logger.trace(" found media mount point {} with type {} -> {}ms", new Object[]{mountInformations[1], mountInformations[2], mediaTimeResolution}); } else { - logger.trace(" found media mount point {} with type {} with option {} -> {}ms", new Object[]{mountInformations[1], mountInformations[2], mediaOption, mediaTimeResolution}); + logger.trace(" found media mount point {} with type {} with option {} -> {}ms", new Object[]{mountInformations[1], mountInformations[2], mediaOption, mediaTimeResolution}); } } if (storageTimeResolution == 0 && mountInformations[1].equals(storageMountPoint)) { @@ -110,7 +118,7 @@ public static int getFilesystemTimeResolutionForTreeUri(Uri startUrl) { } else { storageTimeResolution = 1; } - logger.trace(" found storage mount point {} with type {} -> {}ms", new Object[]{mountInformations[1], mountInformations[2], storageTimeResolution}); + logger.trace(" found storage mount point {} with type {} -> {}ms", new Object[]{mountInformations[1], mountInformations[2], storageTimeResolution}); } if (mediaTimeResolution != 0 && storageTimeResolution != 0) { break; @@ -120,7 +128,9 @@ public static int getFilesystemTimeResolutionForTreeUri(Uri startUrl) { } catch (Exception e) { logger.error("getFilesystemTimeResolutionForTreeUri() {}", e); } - return Math.max(1, Math.max(mediaTimeResolution, storageTimeResolution)); // use 1ms by default + int timeResolution = Math.max(1, Math.max(mediaTimeResolution, storageTimeResolution)); // use 1ms by default + logger.trace(" getFilesystemTimeResolutionForTreeUri({}) -> {}", startUrl, timeResolution); + return timeResolution; } @SuppressLint("ObsoleteSdkInt") From a61737bb92b508b923754507d5778d604d7ee07d Mon Sep 17 00:00:00 2001 From: Laszlo Magyar Date: Thu, 26 Sep 2024 17:39:33 +0200 Subject: [PATCH 05/19] fix time resolution on read also --- primitiveFTPd/src/org/primftpd/filesystem/SafFile.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java b/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java index 58a76a12..b04ae5b8 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java @@ -55,7 +55,7 @@ public SafFile( super( absPath, null, - documentFile.lastModified(), + (documentFile.lastModified() / timeResolution) * timeResolution, documentFile.length(), documentFile.canRead(), documentFile.exists(), From 4d424c84c3880e636407602cb0e75564ad73c956 Mon Sep 17 00:00:00 2001 From: Laszlo Magyar Date: Thu, 26 Sep 2024 21:51:16 +0200 Subject: [PATCH 06/19] harden StorageManagerUtil's exception handling --- .../filesystem/StorageManagerUtil.java | 126 +++++++++--------- 1 file changed, 65 insertions(+), 61 deletions(-) diff --git a/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java b/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java index 4bb49636..c91fc42f 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java @@ -73,60 +73,62 @@ public static int getFilesystemTimeResolutionForTreeUri(Uri startUrl) { int mediaTimeResolution = 0; int storageTimeResolution = 0; String volumeId = getVolumeIdFromTreeUri(startUrl); - String mediaMountPoint = "/mnt/media_rw/" + volumeId; - String mediaOption = null; - String storageMountPoint = "/storage/" + volumeId; - try(BufferedReader br = new BufferedReader(new FileReader("/proc/mounts"))) { - // sample contents for /proc/mounts - // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX vfat ... 0 0 -> 2000 ms - // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX sdfat ...,fs=vfat:16,... 0 0 -> 2000 ms - // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX sdfat ...,fs=vfat:32,... 0 0 -> 2000 ms - // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX sdfat ...,fs=exfat,... 0 0 -> 10 ms - // /mnt/media_rw/XXXX-XXXX /storage/XXXX-XXXX sdcardfs ... 0 0 -> 2000 ms - for (String line; (line = br.readLine()) != null; ) { - logger.trace(" {}", line); - String[] mountInformations = line.split(" "); - if (mountInformations.length >= 4) { - if (mediaTimeResolution == 0 && mountInformations[1].equals(mediaMountPoint)) { - if (mountInformations[2].equals("vfat")) { - mediaTimeResolution = 2000; - } else if (mountInformations[2].equals("sdfat")) { - mediaTimeResolution = 2000; // use 2000ms by default - for (String option : mountInformations[3].split(",")) { - if (option.startsWith("fs=")) { - mediaOption = option; - if (option.startsWith("fs=vfat")) { - mediaTimeResolution = 2000; - } else if (option.startsWith("fs=exfat")) { - mediaTimeResolution = 10; + if (volumeId != null) { + String mediaMountPoint = "/mnt/media_rw/" + volumeId; + String mediaOption = null; + String storageMountPoint = "/storage/" + volumeId; + try(BufferedReader br = new BufferedReader(new FileReader("/proc/mounts"))) { + // sample contents for /proc/mounts + // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX vfat ... 0 0 -> 2000 ms + // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX sdfat ...,fs=vfat:16,... 0 0 -> 2000 ms + // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX sdfat ...,fs=vfat:32,... 0 0 -> 2000 ms + // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX sdfat ...,fs=exfat,... 0 0 -> 10 ms + // /mnt/media_rw/XXXX-XXXX /storage/XXXX-XXXX sdcardfs ... 0 0 -> 2000 ms + for (String line; (line = br.readLine()) != null; ) { + logger.trace(" {}", line); + String[] mountInformations = line.split(" "); + if (mountInformations.length >= 4) { + if (mediaTimeResolution == 0 && mountInformations[1].equals(mediaMountPoint)) { + if (mountInformations[2].equals("vfat")) { + mediaTimeResolution = 2000; + } else if (mountInformations[2].equals("sdfat")) { + mediaTimeResolution = 2000; // use 2000ms by default + for (String option : mountInformations[3].split(",")) { + if (option.startsWith("fs=")) { + mediaOption = option; + if (option.startsWith("fs=vfat")) { + mediaTimeResolution = 2000; + } else if (option.startsWith("fs=exfat")) { + mediaTimeResolution = 10; + } + break; } - break; } + } else { + mediaTimeResolution = 1; + } + if (mediaOption == null) { + logger.trace(" found media mount point {} with type {} -> {}ms", new Object[]{mountInformations[1], mountInformations[2], mediaTimeResolution}); + } else { + logger.trace(" found media mount point {} with type {} with option {} -> {}ms", new Object[]{mountInformations[1], mountInformations[2], mediaOption, mediaTimeResolution}); } - } else { - mediaTimeResolution = 1; } - if (mediaOption == null) { - logger.trace(" found media mount point {} with type {} -> {}ms", new Object[]{mountInformations[1], mountInformations[2], mediaTimeResolution}); - } else { - logger.trace(" found media mount point {} with type {} with option {} -> {}ms", new Object[]{mountInformations[1], mountInformations[2], mediaOption, mediaTimeResolution}); + if (storageTimeResolution == 0 && mountInformations[1].equals(storageMountPoint)) { + if (mountInformations[2].equals("sdcardfs")) { + storageTimeResolution = 2000; + } else { + storageTimeResolution = 1; + } + logger.trace(" found storage mount point {} with type {} -> {}ms", new Object[]{mountInformations[1], mountInformations[2], storageTimeResolution}); } - } - if (storageTimeResolution == 0 && mountInformations[1].equals(storageMountPoint)) { - if (mountInformations[2].equals("sdcardfs")) { - storageTimeResolution = 2000; - } else { - storageTimeResolution = 1; + if (mediaTimeResolution != 0 && storageTimeResolution != 0) { + break; } - logger.trace(" found storage mount point {} with type {} -> {}ms", new Object[]{mountInformations[1], mountInformations[2], storageTimeResolution}); - } - if (mediaTimeResolution != 0 && storageTimeResolution != 0) { - break; } } + } catch (Exception e) { + logger.error("getFilesystemTimeResolutionForTreeUri() {}", e); } - } catch (Exception e) { - logger.error("getFilesystemTimeResolutionForTreeUri() {}", e); } int timeResolution = Math.max(1, Math.max(mediaTimeResolution, storageTimeResolution)); // use 1ms by default logger.trace(" getFilesystemTimeResolutionForTreeUri({}) -> {}", startUrl, timeResolution); @@ -163,32 +165,34 @@ private static String getVolumePath(final String volumeId, Context context) { return (String) getPath.invoke(storageVolumeElement); } } - // not found. - return null; } catch (Exception ex) { - return null; } + return null; } @TargetApi(Build.VERSION_CODES.LOLLIPOP) - public static String getVolumeIdFromTreeUri(final Uri treeUri) { - final String docId = DocumentsContract.getTreeDocumentId(treeUri); - final String[] split = docId.split(":"); - if (split.length > 0) { - return split[0]; - } else { - return null; + private static String getVolumeIdFromTreeUri(final Uri treeUri) { + try { + final String docId = DocumentsContract.getTreeDocumentId(treeUri); + final String[] split = docId.split(":"); + if (split.length > 0) { + return split[0]; + } + } catch (Exception ex) { } + return null; } @TargetApi(Build.VERSION_CODES.LOLLIPOP) private static String getDocumentPathFromTreeUri(final Uri treeUri) { - final String docId = DocumentsContract.getDocumentId(treeUri); - final String[] split = docId.split(":"); - if ((split.length >= 2) && (split[1] != null)) { - return split[1]; - } else { - return File.separator; + try { + final String docId = DocumentsContract.getDocumentId(treeUri); + final String[] split = docId.split(":"); + if ((split.length >= 2) && (split[1] != null)) { + return split[1]; + } + } catch (Exception ex) { } + return File.separator; } } From 5a931f7bef3804444d660ac96023526ad62ce7a0 Mon Sep 17 00:00:00 2001 From: Laszlo Magyar Date: Thu, 26 Sep 2024 22:27:31 +0200 Subject: [PATCH 07/19] fix time resolution inside plain old FS --- .../src/org/primftpd/filesystem/FsFile.java | 9 ++++++--- .../org/primftpd/filesystem/FsFileSystemView.java | 13 ++++++++++++- .../src/org/primftpd/filesystem/FsFtpFile.java | 6 +++--- .../primftpd/filesystem/FsFtpFileSystemView.java | 9 ++++++--- .../src/org/primftpd/filesystem/FsSshFile.java | 15 +++++++++++---- .../primftpd/filesystem/FsSshFileSystemView.java | 9 ++++++--- .../primftpd/filesystem/StorageManagerUtil.java | 14 ++++++++++++++ .../org/primftpd/services/FtpServerService.java | 14 ++++++++++++-- .../org/primftpd/services/SshServerService.java | 14 ++++++++++++-- 9 files changed, 82 insertions(+), 21 deletions(-) diff --git a/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java b/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java index 8243f12a..8916d43b 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java @@ -24,6 +24,7 @@ public abstract class FsFile extends AbstractFile { protected final File file; protected final boolean injectedDirectory; + protected final int timeResolution; private final static Map DIRECTORY_INJECTIONS; static { @@ -48,11 +49,11 @@ public abstract class FsFile extends AbstractFile { INJECTIONS_AND_CHILDREN = Collections.unmodifiableSet(tmp); } - public FsFile(File file, PftpdService pftpdService) { + public FsFile(File file, PftpdService pftpdService, int timeResolution) { super( file.getAbsolutePath(), file.getName(), - file.lastModified(), + (file.lastModified() / timeResolution) * timeResolution, file.length(), file.canRead(), file.exists(), @@ -61,6 +62,7 @@ public FsFile(File file, PftpdService pftpdService) { this.file = file; this.name = file.getName(); this.injectedDirectory = file.isDirectory() && INJECTIONS_AND_CHILDREN.contains(file.getAbsolutePath()); + this.timeResolution = timeResolution; } protected abstract T createFile(File file, PftpdService pftpdService); @@ -144,7 +146,8 @@ public boolean isRemovable() { public boolean setLastModified(long time) { logger.trace("[{}] setLastModified({})", name, Long.valueOf(time)); - return file.setLastModified(time); + long convertedTime = (time / timeResolution) * timeResolution; + return file.setLastModified(convertedTime); } public boolean mkdir() { diff --git a/primitiveFTPd/src/org/primftpd/filesystem/FsFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/FsFileSystemView.java index 33c3d901..414febf0 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/FsFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/FsFileSystemView.java @@ -1,5 +1,8 @@ package org.primftpd.filesystem; +import android.content.Context; +import android.net.Uri; + import org.primftpd.services.PftpdService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -9,16 +12,24 @@ public abstract class FsFileSystemView, X> { protected final Logger logger = LoggerFactory.getLogger(getClass()); + private final String safVolumePath; + private final int safTimeResolution; protected final PftpdService pftpdService; protected abstract T createFile(File file, PftpdService pftpdService); protected abstract String absolute(String file); - public FsFileSystemView(PftpdService pftpdService) { + public FsFileSystemView(Context context, Uri safStartUrl, PftpdService pftpdService) { + this.safTimeResolution = StorageManagerUtil.getFilesystemTimeResolutionForTreeUri(safStartUrl); + this.safVolumePath = safTimeResolution != 1 ? StorageManagerUtil.getVolumePathFromTreeUri(safStartUrl, context) : null; this.pftpdService = pftpdService; } + protected int getTimeResolution(String abs) { + return safVolumePath != null && abs.startsWith(safVolumePath) ? safTimeResolution : 1; + } + public T getFile(String file) { logger.trace("getFile({})", file); String abs = absolute(file); diff --git a/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFile.java b/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFile.java index d06c67f5..69db768d 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFile.java @@ -9,8 +9,8 @@ public class FsFtpFile extends FsFile implements FtpFile { private final User user; - public FsFtpFile(File file, PftpdService pftpdService, User user) { - super(file, pftpdService); + public FsFtpFile(File file, PftpdService pftpdService, int timeResolution, User user) { + super(file, pftpdService, timeResolution); this.user = user; } @@ -21,7 +21,7 @@ public String getClientIp() { @Override protected FtpFile createFile(File file, PftpdService pftpdService) { - return new FsFtpFile(file, pftpdService, user); + return new FsFtpFile(file, pftpdService, timeResolution, user); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFileSystemView.java index b78586d3..83fffb03 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFileSystemView.java @@ -1,5 +1,8 @@ package org.primftpd.filesystem; +import android.content.Context; +import android.net.Uri; + import java.io.File; import org.apache.ftpserver.ftplet.FtpFile; @@ -14,8 +17,8 @@ public class FsFtpFileSystemView extends FsFileSystemView im private final File homeDir; private FsFtpFile workingDir; - public FsFtpFileSystemView(PftpdService pftpdService, File homeDir, User user) { - super(pftpdService); + public FsFtpFileSystemView(Context context, Uri safStartUrl, PftpdService pftpdService, File homeDir, User user) { + super(context, safStartUrl, pftpdService); this.homeDir = homeDir; workingDir = getHomeDirectory(); this.user = user; @@ -23,7 +26,7 @@ public FsFtpFileSystemView(PftpdService pftpdService, File homeDir, User user) { @Override protected FsFtpFile createFile(File file, PftpdService pftpdService) { - return new FsFtpFile(file, pftpdService, user); + return new FsFtpFile(file, pftpdService, getTimeResolution(file.getAbsolutePath()), user); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/FsSshFile.java b/primitiveFTPd/src/org/primftpd/filesystem/FsSshFile.java index 5c3397cb..f6a89467 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/FsSshFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/FsSshFile.java @@ -10,10 +10,12 @@ public class FsSshFile extends FsFile implements SshFile { private final Session session; + private final FsSshFileSystemView fileSystemView; - public FsSshFile(File file, PftpdService pftpdService, Session session) { - super(file, pftpdService); + public FsSshFile(File file, PftpdService pftpdService, int timeResolution, Session session, FsSshFileSystemView fileSystemView) { + super(file, pftpdService, timeResolution); this.session = session; + this.fileSystemView = fileSystemView; } @Override @@ -23,7 +25,7 @@ public String getClientIp() { @Override protected SshFile createFile(File file, PftpdService pftpdService) { - return new FsSshFile(file, pftpdService, session); + return new FsSshFile(file, pftpdService, timeResolution, session, fileSystemView); } @Override @@ -46,7 +48,12 @@ public boolean create() throws IOException { @Override public SshFile getParentFile() { logger.trace("[{}] getParentFile()", name); - return new FsSshFile(file.getParentFile(), pftpdService, session); + String parentPath = file.getParent(); + if (parentPath == null || parentPath.length() == 0) { + parentPath = File.separator; + } + logger.trace("[{}] getParentFile() -> {}", name, parentPath); + return fileSystemView.getFile(parentPath); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/FsSshFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/FsSshFileSystemView.java index 1d556848..04a53c10 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/FsSshFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/FsSshFileSystemView.java @@ -1,5 +1,8 @@ package org.primftpd.filesystem; +import android.content.Context; +import android.net.Uri; + import java.io.File; import org.apache.sshd.common.file.SshFile; @@ -12,15 +15,15 @@ public class FsSshFileSystemView extends FsFileSystemView im private final File homeDir; private final Session session; - public FsSshFileSystemView(PftpdService pftpdService, File homeDir, Session session) { - super(pftpdService); + public FsSshFileSystemView(Context context, Uri safStartUrl, PftpdService pftpdService, File homeDir, Session session) { + super(context, safStartUrl, pftpdService); this.homeDir = homeDir; this.session = session; } @Override protected FsSshFile createFile(File file, PftpdService pftpdService) { - return new FsSshFile(file, pftpdService, session); + return new FsSshFile(file, pftpdService, getTimeResolution(file.getAbsolutePath()), session, this); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java b/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java index c91fc42f..9249e871 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java @@ -54,6 +54,20 @@ public static String getFullDocIdPathFromTreeUri(@Nullable final Uri treeUri, Co } } + public static String getVolumePathFromTreeUri(@Nullable final Uri treeUri, Context context) { + if (treeUri == null) { + return null; + } + String volumePath = getVolumePath(getVolumeIdFromTreeUri(treeUri), context); + if (volumePath == null) { + return null; + } + if (! volumePath.endsWith(File.separator)) { + volumePath += File.separator; + } + return volumePath; + } + /** * This function is to handle 2 Android bugs. *

diff --git a/primitiveFTPd/src/org/primftpd/services/FtpServerService.java b/primitiveFTPd/src/org/primftpd/services/FtpServerService.java index d514dd02..8395c21e 100644 --- a/primitiveFTPd/src/org/primftpd/services/FtpServerService.java +++ b/primitiveFTPd/src/org/primftpd/services/FtpServerService.java @@ -121,7 +121,12 @@ public FileSystemView createFileSystemView(User user) { } else { switch (prefsBean.getStorageType()) { case PLAIN: - return new FsFtpFileSystemView(FtpServerService.this, prefsBean.getStartDir(), user); + return new FsFtpFileSystemView( + getApplicationContext(), + Uri.parse(prefsBean.getSafUrl()), + FtpServerService.this, + prefsBean.getStartDir(), + user); case ROOT: return new RootFtpFileSystemView(shell, FtpServerService.this, prefsBean.getStartDir(), user); case SAF: @@ -139,7 +144,12 @@ public FileSystemView createFileSystemView(User user) { user); case VIRTUAL: return new VirtualFtpFileSystemView( - new FsFtpFileSystemView(FtpServerService.this, prefsBean.getStartDir(), user), + new FsFtpFileSystemView( + getApplicationContext(), + Uri.parse(prefsBean.getSafUrl()), + FtpServerService.this, + prefsBean.getStartDir(), + user), new RootFtpFileSystemView(shell, FtpServerService.this, prefsBean.getStartDir(), user), new SafFtpFileSystemView( getApplicationContext(), diff --git a/primitiveFTPd/src/org/primftpd/services/SshServerService.java b/primitiveFTPd/src/org/primftpd/services/SshServerService.java index 324e6a8a..eff9da90 100644 --- a/primitiveFTPd/src/org/primftpd/services/SshServerService.java +++ b/primitiveFTPd/src/org/primftpd/services/SshServerService.java @@ -206,7 +206,12 @@ public FileSystemView createFileSystemView(Session session) } else { switch (prefsBean.getStorageType()) { case PLAIN: - return new FsSshFileSystemView(SshServerService.this, prefsBean.getStartDir(), session); + return new FsSshFileSystemView( + getApplicationContext(), + Uri.parse(prefsBean.getSafUrl()), + SshServerService.this, + prefsBean.getStartDir(), + session); case ROOT: return new RootSshFileSystemView(shell, SshServerService.this, prefsBean.getStartDir(), session); case SAF: @@ -224,7 +229,12 @@ public FileSystemView createFileSystemView(Session session) session); case VIRTUAL: return new VirtualSshFileSystemView( - new FsSshFileSystemView(SshServerService.this, prefsBean.getStartDir(), session), + new FsSshFileSystemView( + getApplicationContext(), + Uri.parse(prefsBean.getSafUrl()), + SshServerService.this, + prefsBean.getStartDir(), + session), new RootSshFileSystemView(shell, SshServerService.this, prefsBean.getStartDir(), session), new SafSshFileSystemView( getApplicationContext(), From a678fe03ee80165a9f92455fbe079109c1b3a308 Mon Sep 17 00:00:00 2001 From: Laszlo Magyar Date: Thu, 26 Sep 2024 22:44:59 +0200 Subject: [PATCH 08/19] fix time resolution in roSAF --- .../src/org/primftpd/filesystem/RoSafFile.java | 15 +++++++++++---- .../primftpd/filesystem/RoSafFileSystemView.java | 2 ++ .../src/org/primftpd/filesystem/RoSafFtpFile.java | 11 +++++++---- .../filesystem/RoSafFtpFileSystemView.java | 4 ++-- .../src/org/primftpd/filesystem/RoSafSshFile.java | 11 +++++++---- .../filesystem/RoSafSshFileSystemView.java | 4 ++-- 6 files changed, 31 insertions(+), 16 deletions(-) diff --git a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFile.java b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFile.java index 2778ec2f..f0b03b09 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFile.java @@ -21,6 +21,7 @@ public abstract class RoSafFile extends AbstractFile { private final ContentResolver contentResolver; protected final Uri startUrl; + protected final int timeResolution; private String documentId; private boolean writable; @@ -40,7 +41,8 @@ public RoSafFile( ContentResolver contentResolver, Uri startUrl, String absPath, - PftpdService pftpdService) { + PftpdService pftpdService, + int timeResolution) { // this c-tor is to be used for start directory super( absPath, @@ -54,6 +56,7 @@ public RoSafFile( logger.trace(" c-tor 1"); this.contentResolver = contentResolver; this.startUrl = startUrl; + this.timeResolution = timeResolution; try { Cursor cursor = contentResolver.query( @@ -85,7 +88,8 @@ public RoSafFile( String docId, String absPath, boolean exists, - PftpdService pftpdService) { + PftpdService pftpdService, + int timeResolution) { // this c-tor is to be used for FileSystemView.getFile() super( absPath, @@ -99,6 +103,7 @@ public RoSafFile( logger.trace(" c-tor 2"); this.contentResolver = contentResolver; this.startUrl = startUrl; + this.timeResolution = timeResolution; if (exists) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { @@ -130,7 +135,8 @@ public RoSafFile( Uri startUrl, Cursor cursor, String absPath, - PftpdService pftpdService) { + PftpdService pftpdService, + int timeResolution) { // this c-tor is to be used by listFiles() super( absPath, @@ -144,13 +150,14 @@ public RoSafFile( logger.trace(" c-tor 3"); this.contentResolver = contentResolver; this.startUrl = startUrl; + this.timeResolution = timeResolution; initByCursor(cursor); } private void initByCursor(Cursor cursor) { documentId = cursor.getString(0); name = cursor.getString(1); - lastModified = cursor.getLong(2); + lastModified = (cursor.getLong(2) / timeResolution) * timeResolution; size = cursor.getLong(3); logger.trace(" initByCursor, doc id: {}, name: {}", documentId, name); diff --git a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFileSystemView.java index c578216f..ec6f577f 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFileSystemView.java @@ -20,11 +20,13 @@ public abstract class RoSafFileSystemView, X> { protected final Uri startUrl; protected final ContentResolver contentResolver; protected final PftpdService pftpdService; + protected final int timeResolution; public RoSafFileSystemView(Uri startUrl, ContentResolver contentResolver, PftpdService pftpdService) { this.startUrl = startUrl; this.contentResolver = contentResolver; this.pftpdService = pftpdService; + this.timeResolution = StorageManagerUtil.getFilesystemTimeResolutionForTreeUri(startUrl); } protected abstract String absolute(String file); diff --git a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFtpFile.java b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFtpFile.java index 5001d2ab..5b52cedb 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFtpFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFtpFile.java @@ -17,8 +17,9 @@ public RoSafFtpFile( Uri startUrl, String absPath, PftpdService pftpdService, + int timeResolution, User user) { - super(contentResolver, startUrl, absPath, pftpdService); + super(contentResolver, startUrl, absPath, pftpdService, timeResolution); this.user = user; } @@ -29,8 +30,9 @@ public RoSafFtpFile( String absPath, boolean exists, PftpdService pftpdService, + int timeResolution, User user) { - super(contentResolver, startUrl, docId, absPath, exists, pftpdService); + super(contentResolver, startUrl, docId, absPath, exists, pftpdService, timeResolution); this.user = user; } @@ -40,8 +42,9 @@ public RoSafFtpFile( Cursor cursor, String absPath, PftpdService pftpdService, + int timeResolution, User user) { - super(contentResolver, startUrl, cursor, absPath, pftpdService); + super(contentResolver, startUrl, cursor, absPath, pftpdService, timeResolution); this.user = user; } @@ -52,7 +55,7 @@ protected FtpFile createFile( Cursor cursor, String absPath, PftpdService pftpdService) { - return new RoSafFtpFile(contentResolver, startUrl, cursor, absPath, pftpdService, user); + return new RoSafFtpFile(contentResolver, startUrl, cursor, absPath, pftpdService, timeResolution, user); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFtpFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFtpFileSystemView.java index 8d821354..5f814cfd 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFtpFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFtpFileSystemView.java @@ -22,12 +22,12 @@ public RoSafFtpFileSystemView(Uri startUrl, ContentResolver contentResolver, Pft @Override protected RoSafFtpFile createFile(ContentResolver contentResolver, Uri startUrl, String absPath, PftpdService pftpdService) { - return new RoSafFtpFile(contentResolver, startUrl, absPath, pftpdService, user); + return new RoSafFtpFile(contentResolver, startUrl, absPath, pftpdService, timeResolution, user); } @Override protected RoSafFtpFile createFile(ContentResolver contentResolver, Uri startUrl, String docId, String absPath, PftpdService pftpdService) { - return new RoSafFtpFile(contentResolver, startUrl, docId, absPath, true, pftpdService, user); + return new RoSafFtpFile(contentResolver, startUrl, docId, absPath, true, pftpdService, timeResolution, user); } protected RoSafFtpFile createFileNonExistent(ContentResolver contentResolver, Uri startUrl, String name, String absPath, PftpdService pftpdService) { diff --git a/primitiveFTPd/src/org/primftpd/filesystem/RoSafSshFile.java b/primitiveFTPd/src/org/primftpd/filesystem/RoSafSshFile.java index 6c873ac3..85b7bd66 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/RoSafSshFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/RoSafSshFile.java @@ -19,8 +19,9 @@ public RoSafSshFile( Uri startUrl, String absPath, PftpdService pftpdService, + int timeResolution, Session session) { - super(contentResolver, startUrl, absPath, pftpdService); + super(contentResolver, startUrl, absPath, pftpdService, timeResolution); this.session = session; } @@ -31,8 +32,9 @@ public RoSafSshFile( String absPath, boolean exists, PftpdService pftpdService, + int timeResolution, Session session) { - super(contentResolver, startUrl, docId, absPath, exists, pftpdService); + super(contentResolver, startUrl, docId, absPath, exists, pftpdService, timeResolution); this.session = session; } @@ -42,8 +44,9 @@ public RoSafSshFile( Cursor cursor, String absPath, PftpdService pftpdService, + int timeResolution, Session session) { - super(contentResolver, startUrl, cursor, absPath, pftpdService); + super(contentResolver, startUrl, cursor, absPath, pftpdService, timeResolution); this.session = session; } @@ -54,7 +57,7 @@ protected SshFile createFile( Cursor cursor, String absPath, PftpdService pftpdService) { - return new RoSafSshFile(contentResolver, startUrl, cursor, absPath, pftpdService, session); + return new RoSafSshFile(contentResolver, startUrl, cursor, absPath, pftpdService, timeResolution, session); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/RoSafSshFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/RoSafSshFileSystemView.java index 0123fd4d..6c3214a9 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/RoSafSshFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/RoSafSshFileSystemView.java @@ -19,12 +19,12 @@ public RoSafSshFileSystemView(Uri startUrl, ContentResolver contentResolver, Pft @Override protected RoSafSshFile createFile(ContentResolver contentResolver, Uri startUrl, String absPath, PftpdService pftpdService) { - return new RoSafSshFile(contentResolver, startUrl, absPath, pftpdService, session); + return new RoSafSshFile(contentResolver, startUrl, absPath, pftpdService, timeResolution, session); } @Override protected RoSafSshFile createFile(ContentResolver contentResolver, Uri startUrl, String docId, String absPath, PftpdService pftpdService) { - return new RoSafSshFile(contentResolver, startUrl, docId, absPath, true, pftpdService, session); + return new RoSafSshFile(contentResolver, startUrl, docId, absPath, true, pftpdService, timeResolution, session); } @Override From ba72a1fc11e3e2ac2d4b5308aac62a76926aae32 Mon Sep 17 00:00:00 2001 From: Laszlo Magyar Date: Fri, 27 Sep 2024 00:46:57 +0200 Subject: [PATCH 09/19] move fileSystemView up into FsFile --- .../src/org/primftpd/filesystem/FsFile.java | 4 +++- .../primftpd/filesystem/FsFileSystemView.java | 2 +- .../src/org/primftpd/filesystem/FsFtpFile.java | 6 +++--- .../primftpd/filesystem/FsFtpFileSystemView.java | 2 +- .../src/org/primftpd/filesystem/FsSshFile.java | 16 +++++----------- .../primftpd/filesystem/FsSshFileSystemView.java | 2 +- 6 files changed, 14 insertions(+), 18 deletions(-) diff --git a/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java b/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java index 8916d43b..e3a0659f 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java @@ -23,6 +23,7 @@ public abstract class FsFile extends AbstractFile { protected final File file; + protected final FsFileSystemView fileSystemView; protected final boolean injectedDirectory; protected final int timeResolution; @@ -49,7 +50,7 @@ public abstract class FsFile extends AbstractFile { INJECTIONS_AND_CHILDREN = Collections.unmodifiableSet(tmp); } - public FsFile(File file, PftpdService pftpdService, int timeResolution) { + public FsFile(File file, PftpdService pftpdService, int timeResolution, FsFileSystemView fileSystemView) { super( file.getAbsolutePath(), file.getName(), @@ -63,6 +64,7 @@ public FsFile(File file, PftpdService pftpdService, int timeResolution) { this.name = file.getName(); this.injectedDirectory = file.isDirectory() && INJECTIONS_AND_CHILDREN.contains(file.getAbsolutePath()); this.timeResolution = timeResolution; + this.fileSystemView = fileSystemView; } protected abstract T createFile(File file, PftpdService pftpdService); diff --git a/primitiveFTPd/src/org/primftpd/filesystem/FsFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/FsFileSystemView.java index 414febf0..7606d1a1 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/FsFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/FsFileSystemView.java @@ -26,7 +26,7 @@ public FsFileSystemView(Context context, Uri safStartUrl, PftpdService pftpdServ this.pftpdService = pftpdService; } - protected int getTimeResolution(String abs) { + public int getTimeResolution(String abs) { return safVolumePath != null && abs.startsWith(safVolumePath) ? safTimeResolution : 1; } diff --git a/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFile.java b/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFile.java index 69db768d..e5a9f187 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFile.java @@ -9,8 +9,8 @@ public class FsFtpFile extends FsFile implements FtpFile { private final User user; - public FsFtpFile(File file, PftpdService pftpdService, int timeResolution, User user) { - super(file, pftpdService, timeResolution); + public FsFtpFile(File file, PftpdService pftpdService, int timeResolution, FsFtpFileSystemView fileSystemView, User user) { + super(file, pftpdService, timeResolution, fileSystemView); this.user = user; } @@ -21,7 +21,7 @@ public String getClientIp() { @Override protected FtpFile createFile(File file, PftpdService pftpdService) { - return new FsFtpFile(file, pftpdService, timeResolution, user); + return new FsFtpFile(file, pftpdService, fileSystemView.getTimeResolution(file.getAbsolutePath()), (FsFtpFileSystemView)fileSystemView, user); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFileSystemView.java index 83fffb03..09706dcd 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFileSystemView.java @@ -26,7 +26,7 @@ public FsFtpFileSystemView(Context context, Uri safStartUrl, PftpdService pftpdS @Override protected FsFtpFile createFile(File file, PftpdService pftpdService) { - return new FsFtpFile(file, pftpdService, getTimeResolution(file.getAbsolutePath()), user); + return new FsFtpFile(file, pftpdService, getTimeResolution(file.getAbsolutePath()), this, user); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/FsSshFile.java b/primitiveFTPd/src/org/primftpd/filesystem/FsSshFile.java index f6a89467..fcb14a48 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/FsSshFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/FsSshFile.java @@ -10,12 +10,10 @@ public class FsSshFile extends FsFile implements SshFile { private final Session session; - private final FsSshFileSystemView fileSystemView; - public FsSshFile(File file, PftpdService pftpdService, int timeResolution, Session session, FsSshFileSystemView fileSystemView) { - super(file, pftpdService, timeResolution); + public FsSshFile(File file, PftpdService pftpdService, int timeResolution, FsSshFileSystemView fileSystemView, Session session) { + super(file, pftpdService, timeResolution, fileSystemView); this.session = session; - this.fileSystemView = fileSystemView; } @Override @@ -25,7 +23,7 @@ public String getClientIp() { @Override protected SshFile createFile(File file, PftpdService pftpdService) { - return new FsSshFile(file, pftpdService, timeResolution, session, fileSystemView); + return new FsSshFile(file, pftpdService, fileSystemView.getTimeResolution(file.getAbsolutePath()), (FsSshFileSystemView)fileSystemView, session); } @Override @@ -48,12 +46,8 @@ public boolean create() throws IOException { @Override public SshFile getParentFile() { logger.trace("[{}] getParentFile()", name); - String parentPath = file.getParent(); - if (parentPath == null || parentPath.length() == 0) { - parentPath = File.separator; - } - logger.trace("[{}] getParentFile() -> {}", name, parentPath); - return fileSystemView.getFile(parentPath); + File parentFile = file.getParentFile(); + return new FsSshFile(parentFile, pftpdService, fileSystemView.getTimeResolution(parentFile.getAbsolutePath()), (FsSshFileSystemView)fileSystemView, session); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/FsSshFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/FsSshFileSystemView.java index 04a53c10..78c345f8 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/FsSshFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/FsSshFileSystemView.java @@ -23,7 +23,7 @@ public FsSshFileSystemView(Context context, Uri safStartUrl, PftpdService pftpdS @Override protected FsSshFile createFile(File file, PftpdService pftpdService) { - return new FsSshFile(file, pftpdService, getTimeResolution(file.getAbsolutePath()), session, this); + return new FsSshFile(file, pftpdService, getTimeResolution(file.getAbsolutePath()), this, session); } @Override From e668d24afcc90c072edd180bc41a781c2bd0f88c Mon Sep 17 00:00:00 2001 From: Laszlo Magyar Date: Fri, 27 Sep 2024 01:01:26 +0200 Subject: [PATCH 10/19] remove timeResolution as argument from ctors --- .../src/org/primftpd/filesystem/FsFile.java | 12 ++++++++---- .../src/org/primftpd/filesystem/FsFtpFile.java | 6 +++--- .../org/primftpd/filesystem/FsFtpFileSystemView.java | 2 +- .../src/org/primftpd/filesystem/FsSshFile.java | 9 ++++----- .../org/primftpd/filesystem/FsSshFileSystemView.java | 2 +- 5 files changed, 17 insertions(+), 14 deletions(-) diff --git a/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java b/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java index e3a0659f..a4113e2e 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java @@ -50,11 +50,11 @@ public abstract class FsFile extends AbstractFile { INJECTIONS_AND_CHILDREN = Collections.unmodifiableSet(tmp); } - public FsFile(File file, PftpdService pftpdService, int timeResolution, FsFileSystemView fileSystemView) { + public FsFile(File file, PftpdService pftpdService, FsFileSystemView fileSystemView) { super( file.getAbsolutePath(), file.getName(), - (file.lastModified() / timeResolution) * timeResolution, + file.lastModified(), file.length(), file.canRead(), file.exists(), @@ -62,9 +62,13 @@ public FsFile(File file, PftpdService pftpdService, int timeResolution, FsFileSy pftpdService); this.file = file; this.name = file.getName(); - this.injectedDirectory = file.isDirectory() && INJECTIONS_AND_CHILDREN.contains(file.getAbsolutePath()); - this.timeResolution = timeResolution; this.fileSystemView = fileSystemView; + this.injectedDirectory = file.isDirectory() && INJECTIONS_AND_CHILDREN.contains(file.getAbsolutePath()); + this.timeResolution = fileSystemView.getTimeResolution(file.getAbsolutePath()); + + if (timeResolution != 1) { + this.lastModified = (this.lastModified / timeResolution) * timeResolution; + } } protected abstract T createFile(File file, PftpdService pftpdService); diff --git a/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFile.java b/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFile.java index e5a9f187..6bfa210a 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFile.java @@ -9,8 +9,8 @@ public class FsFtpFile extends FsFile implements FtpFile { private final User user; - public FsFtpFile(File file, PftpdService pftpdService, int timeResolution, FsFtpFileSystemView fileSystemView, User user) { - super(file, pftpdService, timeResolution, fileSystemView); + public FsFtpFile(File file, PftpdService pftpdService, FsFtpFileSystemView fileSystemView, User user) { + super(file, pftpdService, fileSystemView); this.user = user; } @@ -21,7 +21,7 @@ public String getClientIp() { @Override protected FtpFile createFile(File file, PftpdService pftpdService) { - return new FsFtpFile(file, pftpdService, fileSystemView.getTimeResolution(file.getAbsolutePath()), (FsFtpFileSystemView)fileSystemView, user); + return new FsFtpFile(file, pftpdService, (FsFtpFileSystemView)fileSystemView, user); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFileSystemView.java index 09706dcd..185eec0a 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFileSystemView.java @@ -26,7 +26,7 @@ public FsFtpFileSystemView(Context context, Uri safStartUrl, PftpdService pftpdS @Override protected FsFtpFile createFile(File file, PftpdService pftpdService) { - return new FsFtpFile(file, pftpdService, getTimeResolution(file.getAbsolutePath()), this, user); + return new FsFtpFile(file, pftpdService, this, user); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/FsSshFile.java b/primitiveFTPd/src/org/primftpd/filesystem/FsSshFile.java index fcb14a48..4b980455 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/FsSshFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/FsSshFile.java @@ -11,8 +11,8 @@ public class FsSshFile extends FsFile implements SshFile { private final Session session; - public FsSshFile(File file, PftpdService pftpdService, int timeResolution, FsSshFileSystemView fileSystemView, Session session) { - super(file, pftpdService, timeResolution, fileSystemView); + public FsSshFile(File file, PftpdService pftpdService, FsSshFileSystemView fileSystemView, Session session) { + super(file, pftpdService, fileSystemView); this.session = session; } @@ -23,7 +23,7 @@ public String getClientIp() { @Override protected SshFile createFile(File file, PftpdService pftpdService) { - return new FsSshFile(file, pftpdService, fileSystemView.getTimeResolution(file.getAbsolutePath()), (FsSshFileSystemView)fileSystemView, session); + return new FsSshFile(file, pftpdService, (FsSshFileSystemView)fileSystemView, session); } @Override @@ -46,8 +46,7 @@ public boolean create() throws IOException { @Override public SshFile getParentFile() { logger.trace("[{}] getParentFile()", name); - File parentFile = file.getParentFile(); - return new FsSshFile(parentFile, pftpdService, fileSystemView.getTimeResolution(parentFile.getAbsolutePath()), (FsSshFileSystemView)fileSystemView, session); + return new FsSshFile(file.getParentFile(), pftpdService, (FsSshFileSystemView)fileSystemView, session); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/FsSshFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/FsSshFileSystemView.java index 78c345f8..a5818701 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/FsSshFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/FsSshFileSystemView.java @@ -23,7 +23,7 @@ public FsSshFileSystemView(Context context, Uri safStartUrl, PftpdService pftpdS @Override protected FsSshFile createFile(File file, PftpdService pftpdService) { - return new FsSshFile(file, pftpdService, getTimeResolution(file.getAbsolutePath()), this, session); + return new FsSshFile(file, pftpdService, this, session); } @Override From 10091d9628498583ca8a693e4dc7c4b666bd90ae Mon Sep 17 00:00:00 2001 From: Laszlo Magyar Date: Fri, 27 Sep 2024 19:26:29 +0200 Subject: [PATCH 11/19] move fileSystemView up into SafFile, RoSafFile, remove timeResolution as argument from ctors --- .../org/primftpd/filesystem/RoSafFile.java | 16 ++++++++------ .../filesystem/RoSafFileSystemView.java | 4 ++++ .../org/primftpd/filesystem/RoSafFtpFile.java | 14 ++++++------- .../filesystem/RoSafFtpFileSystemView.java | 4 ++-- .../org/primftpd/filesystem/RoSafSshFile.java | 14 ++++++------- .../filesystem/RoSafSshFileSystemView.java | 4 ++-- .../src/org/primftpd/filesystem/SafFile.java | 17 ++++++++++----- .../filesystem/SafFileSystemView.java | 4 ++++ .../org/primftpd/filesystem/SafFtpFile.java | 10 ++++----- .../filesystem/SafFtpFileSystemView.java | 4 ++-- .../org/primftpd/filesystem/SafSshFile.java | 21 +++++++------------ .../filesystem/SafSshFileSystemView.java | 4 ++-- 12 files changed, 65 insertions(+), 51 deletions(-) diff --git a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFile.java b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFile.java index f0b03b09..d7d6a081 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFile.java @@ -21,6 +21,7 @@ public abstract class RoSafFile extends AbstractFile { private final ContentResolver contentResolver; protected final Uri startUrl; + protected final RoSafFileSystemView fileSystemView; protected final int timeResolution; private String documentId; @@ -42,7 +43,7 @@ public RoSafFile( Uri startUrl, String absPath, PftpdService pftpdService, - int timeResolution) { + RoSafFileSystemView fileSystemView) { // this c-tor is to be used for start directory super( absPath, @@ -56,7 +57,8 @@ public RoSafFile( logger.trace(" c-tor 1"); this.contentResolver = contentResolver; this.startUrl = startUrl; - this.timeResolution = timeResolution; + this.fileSystemView = fileSystemView; + this.timeResolution = fileSystemView.getTimeResolution(); try { Cursor cursor = contentResolver.query( @@ -89,7 +91,7 @@ public RoSafFile( String absPath, boolean exists, PftpdService pftpdService, - int timeResolution) { + RoSafFileSystemView fileSystemView) { // this c-tor is to be used for FileSystemView.getFile() super( absPath, @@ -103,7 +105,8 @@ public RoSafFile( logger.trace(" c-tor 2"); this.contentResolver = contentResolver; this.startUrl = startUrl; - this.timeResolution = timeResolution; + this.fileSystemView = fileSystemView; + this.timeResolution = fileSystemView.getTimeResolution(); if (exists) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { @@ -136,7 +139,7 @@ public RoSafFile( Cursor cursor, String absPath, PftpdService pftpdService, - int timeResolution) { + RoSafFileSystemView fileSystemView) { // this c-tor is to be used by listFiles() super( absPath, @@ -150,7 +153,8 @@ public RoSafFile( logger.trace(" c-tor 3"); this.contentResolver = contentResolver; this.startUrl = startUrl; - this.timeResolution = timeResolution; + this.fileSystemView = fileSystemView; + this.timeResolution = fileSystemView.getTimeResolution(); initByCursor(cursor); } diff --git a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFileSystemView.java index ec6f577f..29fc62e5 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFileSystemView.java @@ -49,6 +49,10 @@ protected abstract T createFileNonExistent( String absPath, PftpdService pftpdService); + public int getTimeResolution() { + return timeResolution; + } + public T getFile(String file) { logger.trace("getFile({}), startUrl: {}", file, startUrl); diff --git a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFtpFile.java b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFtpFile.java index 5b52cedb..27c4f3d5 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFtpFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFtpFile.java @@ -17,9 +17,9 @@ public RoSafFtpFile( Uri startUrl, String absPath, PftpdService pftpdService, - int timeResolution, + RoSafFtpFileSystemView fileSystemView, User user) { - super(contentResolver, startUrl, absPath, pftpdService, timeResolution); + super(contentResolver, startUrl, absPath, pftpdService, fileSystemView); this.user = user; } @@ -30,9 +30,9 @@ public RoSafFtpFile( String absPath, boolean exists, PftpdService pftpdService, - int timeResolution, + RoSafFtpFileSystemView fileSystemView, User user) { - super(contentResolver, startUrl, docId, absPath, exists, pftpdService, timeResolution); + super(contentResolver, startUrl, docId, absPath, exists, pftpdService, fileSystemView); this.user = user; } @@ -42,9 +42,9 @@ public RoSafFtpFile( Cursor cursor, String absPath, PftpdService pftpdService, - int timeResolution, + RoSafFtpFileSystemView fileSystemView, User user) { - super(contentResolver, startUrl, cursor, absPath, pftpdService, timeResolution); + super(contentResolver, startUrl, cursor, absPath, pftpdService, fileSystemView); this.user = user; } @@ -55,7 +55,7 @@ protected FtpFile createFile( Cursor cursor, String absPath, PftpdService pftpdService) { - return new RoSafFtpFile(contentResolver, startUrl, cursor, absPath, pftpdService, timeResolution, user); + return new RoSafFtpFile(contentResolver, startUrl, cursor, absPath, pftpdService, (RoSafFtpFileSystemView)fileSystemView, user); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFtpFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFtpFileSystemView.java index 5f814cfd..445992df 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFtpFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFtpFileSystemView.java @@ -22,12 +22,12 @@ public RoSafFtpFileSystemView(Uri startUrl, ContentResolver contentResolver, Pft @Override protected RoSafFtpFile createFile(ContentResolver contentResolver, Uri startUrl, String absPath, PftpdService pftpdService) { - return new RoSafFtpFile(contentResolver, startUrl, absPath, pftpdService, timeResolution, user); + return new RoSafFtpFile(contentResolver, startUrl, absPath, pftpdService, this, user); } @Override protected RoSafFtpFile createFile(ContentResolver contentResolver, Uri startUrl, String docId, String absPath, PftpdService pftpdService) { - return new RoSafFtpFile(contentResolver, startUrl, docId, absPath, true, pftpdService, timeResolution, user); + return new RoSafFtpFile(contentResolver, startUrl, docId, absPath, true, pftpdService, this, user); } protected RoSafFtpFile createFileNonExistent(ContentResolver contentResolver, Uri startUrl, String name, String absPath, PftpdService pftpdService) { diff --git a/primitiveFTPd/src/org/primftpd/filesystem/RoSafSshFile.java b/primitiveFTPd/src/org/primftpd/filesystem/RoSafSshFile.java index 85b7bd66..5e3b7ef9 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/RoSafSshFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/RoSafSshFile.java @@ -19,9 +19,9 @@ public RoSafSshFile( Uri startUrl, String absPath, PftpdService pftpdService, - int timeResolution, + RoSafSshFileSystemView fileSystemView, Session session) { - super(contentResolver, startUrl, absPath, pftpdService, timeResolution); + super(contentResolver, startUrl, absPath, pftpdService, fileSystemView); this.session = session; } @@ -32,9 +32,9 @@ public RoSafSshFile( String absPath, boolean exists, PftpdService pftpdService, - int timeResolution, + RoSafSshFileSystemView fileSystemView, Session session) { - super(contentResolver, startUrl, docId, absPath, exists, pftpdService, timeResolution); + super(contentResolver, startUrl, docId, absPath, exists, pftpdService, fileSystemView); this.session = session; } @@ -44,9 +44,9 @@ public RoSafSshFile( Cursor cursor, String absPath, PftpdService pftpdService, - int timeResolution, + RoSafSshFileSystemView fileSystemView, Session session) { - super(contentResolver, startUrl, cursor, absPath, pftpdService, timeResolution); + super(contentResolver, startUrl, cursor, absPath, pftpdService, fileSystemView); this.session = session; } @@ -57,7 +57,7 @@ protected SshFile createFile( Cursor cursor, String absPath, PftpdService pftpdService) { - return new RoSafSshFile(contentResolver, startUrl, cursor, absPath, pftpdService, timeResolution, session); + return new RoSafSshFile(contentResolver, startUrl, cursor, absPath, pftpdService, (RoSafSshFileSystemView)fileSystemView, session); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/RoSafSshFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/RoSafSshFileSystemView.java index 6c3214a9..73ea14c7 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/RoSafSshFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/RoSafSshFileSystemView.java @@ -19,12 +19,12 @@ public RoSafSshFileSystemView(Uri startUrl, ContentResolver contentResolver, Pft @Override protected RoSafSshFile createFile(ContentResolver contentResolver, Uri startUrl, String absPath, PftpdService pftpdService) { - return new RoSafSshFile(contentResolver, startUrl, absPath, pftpdService, timeResolution, session); + return new RoSafSshFile(contentResolver, startUrl, absPath, pftpdService, this, session); } @Override protected RoSafSshFile createFile(ContentResolver contentResolver, Uri startUrl, String docId, String absPath, PftpdService pftpdService) { - return new RoSafSshFile(contentResolver, startUrl, docId, absPath, true, pftpdService, timeResolution, session); + return new RoSafSshFile(contentResolver, startUrl, docId, absPath, true, pftpdService, this, session); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java b/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java index b04ae5b8..52da199b 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java @@ -40,6 +40,7 @@ public abstract class SafFile extends AbstractFile { private DocumentFile documentFile; private final DocumentFile parentDocumentFile; + protected final SafFileSystemView fileSystemView; protected final int timeResolution; private boolean writable; @@ -50,12 +51,12 @@ public SafFile( DocumentFile documentFile, String absPath, PftpdService pftpdService, - int timeResolution) { + SafFileSystemView fileSystemView) { // this c-tor is to be used to access existing files super( absPath, null, - (documentFile.lastModified() / timeResolution) * timeResolution, + documentFile.lastModified(), documentFile.length(), documentFile.canRead(), documentFile.exists(), @@ -67,7 +68,12 @@ public SafFile( this.parentDocumentFile = parentDocumentFile; this.documentFile = documentFile; - this.timeResolution = timeResolution; + this.fileSystemView = fileSystemView; + this.timeResolution = fileSystemView.getTimeResolution(); + + if (timeResolution != 1) { + this.lastModified = (this.lastModified / timeResolution) * timeResolution; + } name = documentFile.getName(); if (name == null && SafFileSystemView.ROOT_PATH.equals(absPath)) { @@ -82,7 +88,7 @@ public SafFile( String name, String absPath, PftpdService pftpdService, - int timeResolution) { + SafFileSystemView fileSystemView) { // this c-tor is to be used to upload new files, create directories or renaming super(absPath, name, 0, 0, false, false, false, pftpdService); String parentName = parentDocumentFile.getName(); @@ -93,7 +99,8 @@ public SafFile( this.writable = true; this.parentDocumentFile = parentDocumentFile; - this.timeResolution = timeResolution; + this.fileSystemView = fileSystemView; + this.timeResolution = fileSystemView.getTimeResolution(); } protected abstract T createFile( diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/SafFileSystemView.java index 39cd163c..8417d26a 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafFileSystemView.java @@ -50,6 +50,10 @@ protected abstract T createFile( protected abstract String absolute(String file); + public int getTimeResolution() { + return timeResolution; + } + public T getFile(String file) { logger.trace("getFile({}), startUrl: {}", file, startUrl); diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFile.java b/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFile.java index cc5ffca6..974373ce 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFile.java @@ -17,9 +17,9 @@ public SafFtpFile( DocumentFile documentFile, String absPath, PftpdService pftpdService, - int timeResolution, + SafFtpFileSystemView fileSystemView, User user) { - super(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, timeResolution); + super(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, fileSystemView); this.user = user; } @@ -29,9 +29,9 @@ public SafFtpFile( String name, String absPath, PftpdService pftpdService, - int timeResolution, + SafFtpFileSystemView fileSystemView, User user) { - super(contentResolver, parentDocumentFile, name, absPath, pftpdService, timeResolution); + super(contentResolver, parentDocumentFile, name, absPath, pftpdService, fileSystemView); this.user = user; } @@ -42,7 +42,7 @@ protected FtpFile createFile( DocumentFile documentFile, String absPath, PftpdService pftpdService) { - return new SafFtpFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, timeResolution, user); + return new SafFtpFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, (SafFtpFileSystemView)fileSystemView, user); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFileSystemView.java index a57a8bd8..95805426 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFileSystemView.java @@ -30,7 +30,7 @@ protected SafFtpFile createFile( String absPath, PftpdService pftpdService) { logger.trace("createFile(DocumentFile)"); - return new SafFtpFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, timeResolution, user); + return new SafFtpFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, this, user); } @Override @@ -41,7 +41,7 @@ protected SafFtpFile createFile( String absPath, PftpdService pftpdService) { logger.trace("createFile(String)"); - return new SafFtpFile(contentResolver, parentDocumentFile, name, absPath, pftpdService, timeResolution, user); + return new SafFtpFile(contentResolver, parentDocumentFile, name, absPath, pftpdService, this, user); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafSshFile.java b/primitiveFTPd/src/org/primftpd/filesystem/SafSshFile.java index ca7777ed..ee069725 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafSshFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafSshFile.java @@ -13,7 +13,6 @@ public class SafSshFile extends SafFile implements SshFile { private final Session session; - private final SafSshFileSystemView fileSystemView; public SafSshFile( ContentResolver contentResolver, @@ -21,12 +20,10 @@ public SafSshFile( DocumentFile documentFile, String absPath, PftpdService pftpdService, - int timeResolution, - Session session, - SafSshFileSystemView fileSystemView) { - super(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, timeResolution); + SafSshFileSystemView fileSystemView, + Session session) { + super(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, fileSystemView); this.session = session; - this.fileSystemView = fileSystemView; } public SafSshFile( @@ -35,12 +32,10 @@ public SafSshFile( String name, String absPath, PftpdService pftpdService, - int timeResolution, - Session session, - SafSshFileSystemView fileSystemView) { - super(contentResolver, parentDocumentFile, name, absPath, pftpdService, timeResolution); + SafSshFileSystemView fileSystemView, + Session session) { + super(contentResolver, parentDocumentFile, name, absPath, pftpdService, fileSystemView); this.session = session; - this.fileSystemView = fileSystemView; } @Override @@ -50,7 +45,7 @@ protected SshFile createFile( DocumentFile documentFile, String absPath, PftpdService pftpdService) { - return new SafSshFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, timeResolution, session, fileSystemView); + return new SafSshFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, (SafSshFileSystemView)fileSystemView, session); } @Override @@ -88,7 +83,7 @@ public SshFile getParentFile() { parentPath = "/"; } logger.trace("[{}] getParentFile() -> {}", name, parentPath); - return fileSystemView.getFile(parentPath); + return (SshFile)fileSystemView.getFile(parentPath); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafSshFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/SafSshFileSystemView.java index 7a93df61..28eaecea 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafSshFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafSshFileSystemView.java @@ -26,7 +26,7 @@ protected SafSshFile createFile( DocumentFile documentFile, String absPath, PftpdService pftpdService) { - return new SafSshFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, timeResolution, session, this); + return new SafSshFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, this, session); } @Override @@ -36,7 +36,7 @@ protected SafSshFile createFile( String name, String absPath, PftpdService pftpdService) { - return new SafSshFile(contentResolver, parentDocumentFile, name, absPath, pftpdService, timeResolution, session, this); + return new SafSshFile(contentResolver, parentDocumentFile, name, absPath, pftpdService, this, session); } @Override From b5b3a89f0dbfc4b159ac07a6e2c7596eb34adc84 Mon Sep 17 00:00:00 2001 From: Laszlo Magyar Date: Fri, 27 Sep 2024 19:33:01 +0200 Subject: [PATCH 12/19] remove timeResolution as class attribute --- primitiveFTPd/src/org/primftpd/filesystem/FsFile.java | 8 +++----- primitiveFTPd/src/org/primftpd/filesystem/RoSafFile.java | 5 +---- primitiveFTPd/src/org/primftpd/filesystem/SafFile.java | 9 +++------ 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java b/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java index a4113e2e..401eaba7 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java @@ -25,7 +25,6 @@ public abstract class FsFile extends AbstractFile { protected final File file; protected final FsFileSystemView fileSystemView; protected final boolean injectedDirectory; - protected final int timeResolution; private final static Map DIRECTORY_INJECTIONS; static { @@ -64,11 +63,9 @@ public FsFile(File file, PftpdService pftpdService, FsFileSystemView fileSystemV this.name = file.getName(); this.fileSystemView = fileSystemView; this.injectedDirectory = file.isDirectory() && INJECTIONS_AND_CHILDREN.contains(file.getAbsolutePath()); - this.timeResolution = fileSystemView.getTimeResolution(file.getAbsolutePath()); - if (timeResolution != 1) { - this.lastModified = (this.lastModified / timeResolution) * timeResolution; - } + int timeResolution = fileSystemView.getTimeResolution(file.getAbsolutePath()); + this.lastModified = (this.lastModified / timeResolution) * timeResolution; } protected abstract T createFile(File file, PftpdService pftpdService); @@ -152,6 +149,7 @@ public boolean isRemovable() { public boolean setLastModified(long time) { logger.trace("[{}] setLastModified({})", name, Long.valueOf(time)); + int timeResolution = fileSystemView.getTimeResolution(file.getAbsolutePath()); long convertedTime = (time / timeResolution) * timeResolution; return file.setLastModified(convertedTime); } diff --git a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFile.java b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFile.java index d7d6a081..442cbdba 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFile.java @@ -22,7 +22,6 @@ public abstract class RoSafFile extends AbstractFile { private final ContentResolver contentResolver; protected final Uri startUrl; protected final RoSafFileSystemView fileSystemView; - protected final int timeResolution; private String documentId; private boolean writable; @@ -58,7 +57,6 @@ public RoSafFile( this.contentResolver = contentResolver; this.startUrl = startUrl; this.fileSystemView = fileSystemView; - this.timeResolution = fileSystemView.getTimeResolution(); try { Cursor cursor = contentResolver.query( @@ -106,7 +104,6 @@ public RoSafFile( this.contentResolver = contentResolver; this.startUrl = startUrl; this.fileSystemView = fileSystemView; - this.timeResolution = fileSystemView.getTimeResolution(); if (exists) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { @@ -154,13 +151,13 @@ public RoSafFile( this.contentResolver = contentResolver; this.startUrl = startUrl; this.fileSystemView = fileSystemView; - this.timeResolution = fileSystemView.getTimeResolution(); initByCursor(cursor); } private void initByCursor(Cursor cursor) { documentId = cursor.getString(0); name = cursor.getString(1); + int timeResolution = fileSystemView.getTimeResolution(); lastModified = (cursor.getLong(2) / timeResolution) * timeResolution; size = cursor.getLong(3); diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java b/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java index 52da199b..5b1a1a60 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java @@ -41,7 +41,6 @@ public abstract class SafFile extends AbstractFile { private DocumentFile documentFile; private final DocumentFile parentDocumentFile; protected final SafFileSystemView fileSystemView; - protected final int timeResolution; private boolean writable; @@ -69,11 +68,9 @@ public SafFile( this.parentDocumentFile = parentDocumentFile; this.documentFile = documentFile; this.fileSystemView = fileSystemView; - this.timeResolution = fileSystemView.getTimeResolution(); - if (timeResolution != 1) { - this.lastModified = (this.lastModified / timeResolution) * timeResolution; - } + int timeResolution = fileSystemView.getTimeResolution(); + this.lastModified = (this.lastModified / timeResolution) * timeResolution; name = documentFile.getName(); if (name == null && SafFileSystemView.ROOT_PATH.equals(absPath)) { @@ -100,7 +97,6 @@ public SafFile( this.parentDocumentFile = parentDocumentFile; this.fileSystemView = fileSystemView; - this.timeResolution = fileSystemView.getTimeResolution(); } protected abstract T createFile( @@ -139,6 +135,7 @@ public boolean setLastModified(long time) { try { Uri docUri = documentFile.getUri(); Path filePath = Paths.get(StorageManagerUtil.getFullDocIdPathFromTreeUri(docUri, pftpdService.getContext())); + int timeResolution = fileSystemView.getTimeResolution(); long convertedTime = (time / timeResolution) * timeResolution; Files.getFileAttributeView(filePath, BasicFileAttributeView.class).setTimes(FileTime.fromMillis(convertedTime), null, null); } catch (Exception e) { From 08d6f50677ed63adca32db6a40dc0c97a1c53cac Mon Sep 17 00:00:00 2001 From: Laszlo Magyar Date: Fri, 27 Sep 2024 19:45:10 +0200 Subject: [PATCH 13/19] space/tab --- primitiveFTPd/src/org/primftpd/filesystem/FsFile.java | 4 ++-- .../src/org/primftpd/filesystem/FsFileSystemView.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java b/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java index 401eaba7..17da294e 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java @@ -23,7 +23,7 @@ public abstract class FsFile extends AbstractFile { protected final File file; - protected final FsFileSystemView fileSystemView; + protected final FsFileSystemView fileSystemView; protected final boolean injectedDirectory; private final static Map DIRECTORY_INJECTIONS; @@ -47,7 +47,7 @@ public abstract class FsFile extends AbstractFile { } } INJECTIONS_AND_CHILDREN = Collections.unmodifiableSet(tmp); - } + } public FsFile(File file, PftpdService pftpdService, FsFileSystemView fileSystemView) { super( diff --git a/primitiveFTPd/src/org/primftpd/filesystem/FsFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/FsFileSystemView.java index 7606d1a1..704900cb 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/FsFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/FsFileSystemView.java @@ -21,7 +21,7 @@ public abstract class FsFileSystemView, X> { protected abstract String absolute(String file); public FsFileSystemView(Context context, Uri safStartUrl, PftpdService pftpdService) { - this.safTimeResolution = StorageManagerUtil.getFilesystemTimeResolutionForTreeUri(safStartUrl); + this.safTimeResolution = StorageManagerUtil.getFilesystemTimeResolutionForTreeUri(safStartUrl); this.safVolumePath = safTimeResolution != 1 ? StorageManagerUtil.getVolumePathFromTreeUri(safStartUrl, context) : null; this.pftpdService = pftpdService; } From 39a5553e7842462875d5e03443ab2fe4b7c779fa Mon Sep 17 00:00:00 2001 From: Laszlo Magyar Date: Fri, 27 Sep 2024 19:52:34 +0200 Subject: [PATCH 14/19] minimize casting on fileSystemView --- primitiveFTPd/src/org/primftpd/filesystem/FsFtpFile.java | 6 +++++- primitiveFTPd/src/org/primftpd/filesystem/FsSshFile.java | 8 ++++++-- .../src/org/primftpd/filesystem/RoSafFtpFile.java | 6 +++++- .../src/org/primftpd/filesystem/RoSafSshFile.java | 6 +++++- primitiveFTPd/src/org/primftpd/filesystem/SafFtpFile.java | 6 +++++- primitiveFTPd/src/org/primftpd/filesystem/SafSshFile.java | 8 ++++++-- 6 files changed, 32 insertions(+), 8 deletions(-) diff --git a/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFile.java b/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFile.java index 6bfa210a..81e6f543 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/FsFtpFile.java @@ -14,6 +14,10 @@ public FsFtpFile(File file, PftpdService pftpdService, FsFtpFileSystemView fileS this.user = user; } + private FsFtpFileSystemView getFileSystemView() { + return (FsFtpFileSystemView)fileSystemView; + } + @Override public String getClientIp() { return FtpUtils.getClientIp(user); @@ -21,7 +25,7 @@ public String getClientIp() { @Override protected FtpFile createFile(File file, PftpdService pftpdService) { - return new FsFtpFile(file, pftpdService, (FsFtpFileSystemView)fileSystemView, user); + return new FsFtpFile(file, pftpdService, getFileSystemView(), user); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/FsSshFile.java b/primitiveFTPd/src/org/primftpd/filesystem/FsSshFile.java index 4b980455..a59b0415 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/FsSshFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/FsSshFile.java @@ -16,6 +16,10 @@ public FsSshFile(File file, PftpdService pftpdService, FsSshFileSystemView fileS this.session = session; } + private FsSshFileSystemView getFileSystemView() { + return (FsSshFileSystemView)fileSystemView; + } + @Override public String getClientIp() { return SshUtils.getClientIp(session); @@ -23,7 +27,7 @@ public String getClientIp() { @Override protected SshFile createFile(File file, PftpdService pftpdService) { - return new FsSshFile(file, pftpdService, (FsSshFileSystemView)fileSystemView, session); + return new FsSshFile(file, pftpdService, getFileSystemView(), session); } @Override @@ -46,7 +50,7 @@ public boolean create() throws IOException { @Override public SshFile getParentFile() { logger.trace("[{}] getParentFile()", name); - return new FsSshFile(file.getParentFile(), pftpdService, (FsSshFileSystemView)fileSystemView, session); + return new FsSshFile(file.getParentFile(), pftpdService, getFileSystemView(), session); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFtpFile.java b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFtpFile.java index 27c4f3d5..9ed81857 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFtpFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFtpFile.java @@ -48,6 +48,10 @@ public RoSafFtpFile( this.user = user; } + private RoSafFtpFileSystemView getFileSystemView() { + return (RoSafFtpFileSystemView)fileSystemView; + } + @Override protected FtpFile createFile( ContentResolver contentResolver, @@ -55,7 +59,7 @@ protected FtpFile createFile( Cursor cursor, String absPath, PftpdService pftpdService) { - return new RoSafFtpFile(contentResolver, startUrl, cursor, absPath, pftpdService, (RoSafFtpFileSystemView)fileSystemView, user); + return new RoSafFtpFile(contentResolver, startUrl, cursor, absPath, pftpdService, getFileSystemView(), user); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/RoSafSshFile.java b/primitiveFTPd/src/org/primftpd/filesystem/RoSafSshFile.java index 5e3b7ef9..eb60ed5a 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/RoSafSshFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/RoSafSshFile.java @@ -50,6 +50,10 @@ public RoSafSshFile( this.session = session; } + private RoSafSshFileSystemView getFileSystemView() { + return (RoSafSshFileSystemView)fileSystemView; + } + @Override protected SshFile createFile( ContentResolver contentResolver, @@ -57,7 +61,7 @@ protected SshFile createFile( Cursor cursor, String absPath, PftpdService pftpdService) { - return new RoSafSshFile(contentResolver, startUrl, cursor, absPath, pftpdService, (RoSafSshFileSystemView)fileSystemView, session); + return new RoSafSshFile(contentResolver, startUrl, cursor, absPath, pftpdService, getFileSystemView(), session); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFile.java b/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFile.java index 974373ce..6dbabd94 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafFtpFile.java @@ -35,6 +35,10 @@ public SafFtpFile( this.user = user; } + private SafFtpFileSystemView getFileSystemView() { + return (SafFtpFileSystemView)fileSystemView; + } + @Override protected FtpFile createFile( ContentResolver contentResolver, @@ -42,7 +46,7 @@ protected FtpFile createFile( DocumentFile documentFile, String absPath, PftpdService pftpdService) { - return new SafFtpFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, (SafFtpFileSystemView)fileSystemView, user); + return new SafFtpFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, getFileSystemView(), user); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafSshFile.java b/primitiveFTPd/src/org/primftpd/filesystem/SafSshFile.java index ee069725..6217697e 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafSshFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafSshFile.java @@ -38,6 +38,10 @@ public SafSshFile( this.session = session; } + private SafSshFileSystemView getFileSystemView() { + return (SafSshFileSystemView)fileSystemView; + } + @Override protected SshFile createFile( ContentResolver contentResolver, @@ -45,7 +49,7 @@ protected SshFile createFile( DocumentFile documentFile, String absPath, PftpdService pftpdService) { - return new SafSshFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, (SafSshFileSystemView)fileSystemView, session); + return new SafSshFile(contentResolver, parentDocumentFile, documentFile, absPath, pftpdService, getFileSystemView(), session); } @Override @@ -83,7 +87,7 @@ public SshFile getParentFile() { parentPath = "/"; } logger.trace("[{}] getParentFile() -> {}", name, parentPath); - return (SshFile)fileSystemView.getFile(parentPath); + return getFileSystemView().getFile(parentPath); } @Override From 3de41b26b1147b7252aaf811b3b8d1e1f0bf6aea Mon Sep 17 00:00:00 2001 From: Laszlo Magyar Date: Sun, 29 Sep 2024 22:31:36 +0200 Subject: [PATCH 15/19] cache time resolutions --- .../filesystem/StorageManagerUtil.java | 108 ++++++++++-------- 1 file changed, 60 insertions(+), 48 deletions(-) diff --git a/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java b/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java index 9249e871..19d4fae3 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/StorageManagerUtil.java @@ -20,6 +20,8 @@ import java.io.FileReader; import java.lang.reflect.Array; import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; public final class StorageManagerUtil { private static final String PRIMARY_VOLUME_NAME = "primary"; @@ -68,6 +70,8 @@ public static String getVolumePathFromTreeUri(@Nullable final Uri treeUri, Conte return volumePath; } + private final static Map cachedFilesystemTimeResolutions = new HashMap<>(); + /** * This function is to handle 2 Android bugs. *

@@ -84,67 +88,75 @@ public static String getVolumePathFromTreeUri(@Nullable final Uri treeUri, Conte */ public static int getFilesystemTimeResolutionForTreeUri(Uri startUrl) { logger.trace("getFilesystemTimeResolutionForTreeUri({})", startUrl); - int mediaTimeResolution = 0; - int storageTimeResolution = 0; + int timeResolution = 1; // use 1ms by default String volumeId = getVolumeIdFromTreeUri(startUrl); if (volumeId != null) { - String mediaMountPoint = "/mnt/media_rw/" + volumeId; - String mediaOption = null; - String storageMountPoint = "/storage/" + volumeId; - try(BufferedReader br = new BufferedReader(new FileReader("/proc/mounts"))) { - // sample contents for /proc/mounts - // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX vfat ... 0 0 -> 2000 ms - // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX sdfat ...,fs=vfat:16,... 0 0 -> 2000 ms - // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX sdfat ...,fs=vfat:32,... 0 0 -> 2000 ms - // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX sdfat ...,fs=exfat,... 0 0 -> 10 ms - // /mnt/media_rw/XXXX-XXXX /storage/XXXX-XXXX sdcardfs ... 0 0 -> 2000 ms - for (String line; (line = br.readLine()) != null; ) { - logger.trace(" {}", line); - String[] mountInformations = line.split(" "); - if (mountInformations.length >= 4) { - if (mediaTimeResolution == 0 && mountInformations[1].equals(mediaMountPoint)) { - if (mountInformations[2].equals("vfat")) { - mediaTimeResolution = 2000; - } else if (mountInformations[2].equals("sdfat")) { - mediaTimeResolution = 2000; // use 2000ms by default - for (String option : mountInformations[3].split(",")) { - if (option.startsWith("fs=")) { - mediaOption = option; - if (option.startsWith("fs=vfat")) { - mediaTimeResolution = 2000; - } else if (option.startsWith("fs=exfat")) { - mediaTimeResolution = 10; + Integer cachedTimeResolution = cachedFilesystemTimeResolutions.get(volumeId); + if (cachedTimeResolution != null) { + timeResolution = cachedTimeResolution.intValue(); + logger.trace(" used cached value"); + } else { + int mediaTimeResolution = 0; + int storageTimeResolution = 0; + String mediaMountPoint = "/mnt/media_rw/" + volumeId; + String mediaOption = null; + String storageMountPoint = "/storage/" + volumeId; + try(BufferedReader br = new BufferedReader(new FileReader("/proc/mounts"))) { + // sample contents for /proc/mounts + // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX vfat ... 0 0 -> 2000 ms + // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX sdfat ...,fs=vfat:16,... 0 0 -> 2000 ms + // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX sdfat ...,fs=vfat:32,... 0 0 -> 2000 ms + // /dev/block/vold/public:xxx,xx /mnt/media_rw/XXXX-XXXX sdfat ...,fs=exfat,... 0 0 -> 10 ms + // /mnt/media_rw/XXXX-XXXX /storage/XXXX-XXXX sdcardfs ... 0 0 -> 2000 ms + for (String line; (line = br.readLine()) != null; ) { + logger.trace(" {}", line); + String[] mountInformations = line.split(" "); + if (mountInformations.length >= 4) { + if (mediaTimeResolution == 0 && mountInformations[1].equals(mediaMountPoint)) { + if (mountInformations[2].equals("vfat")) { + mediaTimeResolution = 2000; + } else if (mountInformations[2].equals("sdfat")) { + mediaTimeResolution = 2000; // use 2000ms by default + for (String option : mountInformations[3].split(",")) { + if (option.startsWith("fs=")) { + mediaOption = option; + if (option.startsWith("fs=vfat")) { + mediaTimeResolution = 2000; + } else if (option.startsWith("fs=exfat")) { + mediaTimeResolution = 10; + } + break; } - break; } + } else { + mediaTimeResolution = 1; + } + if (mediaOption == null) { + logger.trace(" found media mount point {} with type {} -> {}ms", new Object[]{mountInformations[1], mountInformations[2], mediaTimeResolution}); + } else { + logger.trace(" found media mount point {} with type {} with option {} -> {}ms", new Object[]{mountInformations[1], mountInformations[2], mediaOption, mediaTimeResolution}); } - } else { - mediaTimeResolution = 1; } - if (mediaOption == null) { - logger.trace(" found media mount point {} with type {} -> {}ms", new Object[]{mountInformations[1], mountInformations[2], mediaTimeResolution}); - } else { - logger.trace(" found media mount point {} with type {} with option {} -> {}ms", new Object[]{mountInformations[1], mountInformations[2], mediaOption, mediaTimeResolution}); + if (storageTimeResolution == 0 && mountInformations[1].equals(storageMountPoint)) { + if (mountInformations[2].equals("sdcardfs")) { + storageTimeResolution = 2000; + } else { + storageTimeResolution = 1; + } + logger.trace(" found storage mount point {} with type {} -> {}ms", new Object[]{mountInformations[1], mountInformations[2], storageTimeResolution}); } - } - if (storageTimeResolution == 0 && mountInformations[1].equals(storageMountPoint)) { - if (mountInformations[2].equals("sdcardfs")) { - storageTimeResolution = 2000; - } else { - storageTimeResolution = 1; + if (mediaTimeResolution != 0 && storageTimeResolution != 0) { + break; } - logger.trace(" found storage mount point {} with type {} -> {}ms", new Object[]{mountInformations[1], mountInformations[2], storageTimeResolution}); - } - if (mediaTimeResolution != 0 && storageTimeResolution != 0) { - break; } } + timeResolution = Math.max(timeResolution, Math.max(mediaTimeResolution, storageTimeResolution)); + cachedFilesystemTimeResolutions.put(volumeId, timeResolution); + } catch (Exception e) { + logger.error("getFilesystemTimeResolutionForTreeUri() {}", e); } - } catch (Exception e) { - logger.error("getFilesystemTimeResolutionForTreeUri() {}", e); } } - int timeResolution = Math.max(1, Math.max(mediaTimeResolution, storageTimeResolution)); // use 1ms by default logger.trace(" getFilesystemTimeResolutionForTreeUri({}) -> {}", startUrl, timeResolution); return timeResolution; } From 384b53f404bf74e008c35c5f801e0e203e56ee70 Mon Sep 17 00:00:00 2001 From: Laszlo Magyar Date: Sun, 29 Sep 2024 22:39:39 +0200 Subject: [PATCH 16/19] put time resolution calculation into static method --- .../src/org/primftpd/filesystem/FsFile.java | 13 +++++++------ .../src/org/primftpd/filesystem/RoSafFile.java | 8 ++++++-- .../src/org/primftpd/filesystem/SafFile.java | 16 +++++++++------- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java b/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java index 17da294e..a75826dd 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java @@ -53,7 +53,7 @@ public FsFile(File file, PftpdService pftpdService, FsFileSystemView fileSystemV super( file.getAbsolutePath(), file.getName(), - file.lastModified(), + correctTime(fileSystemView, file.getAbsolutePath(), file.lastModified()), file.length(), file.canRead(), file.exists(), @@ -63,9 +63,11 @@ public FsFile(File file, PftpdService pftpdService, FsFileSystemView fileSystemV this.name = file.getName(); this.fileSystemView = fileSystemView; this.injectedDirectory = file.isDirectory() && INJECTIONS_AND_CHILDREN.contains(file.getAbsolutePath()); + } - int timeResolution = fileSystemView.getTimeResolution(file.getAbsolutePath()); - this.lastModified = (this.lastModified / timeResolution) * timeResolution; + private static long correctTime(FsFileSystemView fileSystemView, String abs, long time) { + int timeResolution = fileSystemView.getTimeResolution(abs); + return (time / timeResolution) * timeResolution; } protected abstract T createFile(File file, PftpdService pftpdService); @@ -149,9 +151,8 @@ public boolean isRemovable() { public boolean setLastModified(long time) { logger.trace("[{}] setLastModified({})", name, Long.valueOf(time)); - int timeResolution = fileSystemView.getTimeResolution(file.getAbsolutePath()); - long convertedTime = (time / timeResolution) * timeResolution; - return file.setLastModified(convertedTime); + long correctedTime = correctTime(fileSystemView, absPath, time); + return file.setLastModified(correctedTime); } public boolean mkdir() { diff --git a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFile.java b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFile.java index 442cbdba..843bad5a 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFile.java @@ -157,8 +157,7 @@ public RoSafFile( private void initByCursor(Cursor cursor) { documentId = cursor.getString(0); name = cursor.getString(1); - int timeResolution = fileSystemView.getTimeResolution(); - lastModified = (cursor.getLong(2) / timeResolution) * timeResolution; + lastModified = correctTime(this.fileSystemView, cursor.getLong(2)); size = cursor.getLong(3); logger.trace(" initByCursor, doc id: {}, name: {}", documentId, name); @@ -178,6 +177,11 @@ private boolean flagPresent(int flags, int flag) { return ((flags & flag) == flag); } + private static long correctTime(RoSafFileSystemView fileSystemView, long time) { + int timeResolution = fileSystemView.getTimeResolution(); + return (time / timeResolution) * timeResolution; + } + protected abstract T createFile( ContentResolver contentResolver, Uri startUrl, diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java b/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java index 5b1a1a60..345140f6 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java @@ -55,7 +55,7 @@ public SafFile( super( absPath, null, - documentFile.lastModified(), + correctTime(fileSystemView, documentFile.lastModified()), documentFile.length(), documentFile.canRead(), documentFile.exists(), @@ -69,9 +69,6 @@ public SafFile( this.documentFile = documentFile; this.fileSystemView = fileSystemView; - int timeResolution = fileSystemView.getTimeResolution(); - this.lastModified = (this.lastModified / timeResolution) * timeResolution; - name = documentFile.getName(); if (name == null && SafFileSystemView.ROOT_PATH.equals(absPath)) { name = SafFileSystemView.ROOT_PATH; @@ -99,6 +96,11 @@ public SafFile( this.fileSystemView = fileSystemView; } + private static long correctTime(SafFileSystemView fileSystemView, long time) { + int timeResolution = fileSystemView.getTimeResolution(); + return (time / timeResolution) * timeResolution; + } + protected abstract T createFile( ContentResolver contentResolver, DocumentFile parentDocumentFile, @@ -135,9 +137,9 @@ public boolean setLastModified(long time) { try { Uri docUri = documentFile.getUri(); Path filePath = Paths.get(StorageManagerUtil.getFullDocIdPathFromTreeUri(docUri, pftpdService.getContext())); - int timeResolution = fileSystemView.getTimeResolution(); - long convertedTime = (time / timeResolution) * timeResolution; - Files.getFileAttributeView(filePath, BasicFileAttributeView.class).setTimes(FileTime.fromMillis(convertedTime), null, null); + long correctedTime = correctTime(fileSystemView, time); + Files.getFileAttributeView(filePath, BasicFileAttributeView.class).setTimes(FileTime.fromMillis(correctedTime), null, null); + return true; } catch (Exception e) { String baseMsg = "could not set last modified time"; logger.error(baseMsg, e); From 08ea5dbb0b257228c61e521b2755baf9a81b7813 Mon Sep 17 00:00:00 2001 From: Laszlo Magyar Date: Sun, 29 Sep 2024 22:48:28 +0200 Subject: [PATCH 17/19] fsView corrects the time --- primitiveFTPd/src/org/primftpd/filesystem/FsFile.java | 9 ++------- .../src/org/primftpd/filesystem/FsFileSystemView.java | 5 +++-- primitiveFTPd/src/org/primftpd/filesystem/RoSafFile.java | 7 +------ .../src/org/primftpd/filesystem/RoSafFileSystemView.java | 4 ++-- primitiveFTPd/src/org/primftpd/filesystem/SafFile.java | 9 ++------- .../src/org/primftpd/filesystem/SafFileSystemView.java | 4 ++-- 6 files changed, 12 insertions(+), 26 deletions(-) diff --git a/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java b/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java index a75826dd..b482e9f9 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/FsFile.java @@ -53,7 +53,7 @@ public FsFile(File file, PftpdService pftpdService, FsFileSystemView fileSystemV super( file.getAbsolutePath(), file.getName(), - correctTime(fileSystemView, file.getAbsolutePath(), file.lastModified()), + fileSystemView.getCorrectedTime(file.getAbsolutePath(), file.lastModified()), file.length(), file.canRead(), file.exists(), @@ -65,11 +65,6 @@ public FsFile(File file, PftpdService pftpdService, FsFileSystemView fileSystemV this.injectedDirectory = file.isDirectory() && INJECTIONS_AND_CHILDREN.contains(file.getAbsolutePath()); } - private static long correctTime(FsFileSystemView fileSystemView, String abs, long time) { - int timeResolution = fileSystemView.getTimeResolution(abs); - return (time / timeResolution) * timeResolution; - } - protected abstract T createFile(File file, PftpdService pftpdService); @Override @@ -151,7 +146,7 @@ public boolean isRemovable() { public boolean setLastModified(long time) { logger.trace("[{}] setLastModified({})", name, Long.valueOf(time)); - long correctedTime = correctTime(fileSystemView, absPath, time); + long correctedTime = fileSystemView.getCorrectedTime(absPath, time); return file.setLastModified(correctedTime); } diff --git a/primitiveFTPd/src/org/primftpd/filesystem/FsFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/FsFileSystemView.java index 704900cb..d8939380 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/FsFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/FsFileSystemView.java @@ -26,8 +26,9 @@ public FsFileSystemView(Context context, Uri safStartUrl, PftpdService pftpdServ this.pftpdService = pftpdService; } - public int getTimeResolution(String abs) { - return safVolumePath != null && abs.startsWith(safVolumePath) ? safTimeResolution : 1; + public long getCorrectedTime(String abs, long time) { + int timeResolution = safVolumePath != null && abs.startsWith(safVolumePath) ? safTimeResolution : 1; + return (time / timeResolution) * timeResolution; } public T getFile(String file) { diff --git a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFile.java b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFile.java index 843bad5a..e57d22fe 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFile.java @@ -157,7 +157,7 @@ public RoSafFile( private void initByCursor(Cursor cursor) { documentId = cursor.getString(0); name = cursor.getString(1); - lastModified = correctTime(this.fileSystemView, cursor.getLong(2)); + lastModified = fileSystemView.getCorrectedTime(cursor.getLong(2)); size = cursor.getLong(3); logger.trace(" initByCursor, doc id: {}, name: {}", documentId, name); @@ -177,11 +177,6 @@ private boolean flagPresent(int flags, int flag) { return ((flags & flag) == flag); } - private static long correctTime(RoSafFileSystemView fileSystemView, long time) { - int timeResolution = fileSystemView.getTimeResolution(); - return (time / timeResolution) * timeResolution; - } - protected abstract T createFile( ContentResolver contentResolver, Uri startUrl, diff --git a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFileSystemView.java index 29fc62e5..c032505a 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFileSystemView.java @@ -49,8 +49,8 @@ protected abstract T createFileNonExistent( String absPath, PftpdService pftpdService); - public int getTimeResolution() { - return timeResolution; + public long getCorrectedTime(long time) { + return (time / timeResolution) * timeResolution; } public T getFile(String file) { diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java b/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java index 345140f6..481be02b 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java @@ -55,7 +55,7 @@ public SafFile( super( absPath, null, - correctTime(fileSystemView, documentFile.lastModified()), + fileSystemView.getCorrectedTime(documentFile.lastModified()), documentFile.length(), documentFile.canRead(), documentFile.exists(), @@ -96,11 +96,6 @@ public SafFile( this.fileSystemView = fileSystemView; } - private static long correctTime(SafFileSystemView fileSystemView, long time) { - int timeResolution = fileSystemView.getTimeResolution(); - return (time / timeResolution) * timeResolution; - } - protected abstract T createFile( ContentResolver contentResolver, DocumentFile parentDocumentFile, @@ -137,7 +132,7 @@ public boolean setLastModified(long time) { try { Uri docUri = documentFile.getUri(); Path filePath = Paths.get(StorageManagerUtil.getFullDocIdPathFromTreeUri(docUri, pftpdService.getContext())); - long correctedTime = correctTime(fileSystemView, time); + long correctedTime = fileSystemView.getCorrectedTime(time); Files.getFileAttributeView(filePath, BasicFileAttributeView.class).setTimes(FileTime.fromMillis(correctedTime), null, null); return true; } catch (Exception e) { diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/SafFileSystemView.java index 8417d26a..c6d21e7b 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafFileSystemView.java @@ -50,8 +50,8 @@ protected abstract T createFile( protected abstract String absolute(String file); - public int getTimeResolution() { - return timeResolution; + public long getCorrectedTime(long time) { + return (time / timeResolution) * timeResolution; } public T getFile(String file) { From 58b0731e95ed3dbb66a52a7c1b249062efd14923 Mon Sep 17 00:00:00 2001 From: Laszlo Magyar Date: Sun, 29 Sep 2024 23:37:04 +0200 Subject: [PATCH 18/19] one more lastModified() --- primitiveFTPd/src/org/primftpd/filesystem/SafFile.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java b/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java index 481be02b..032234c0 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/SafFile.java @@ -246,7 +246,7 @@ boolean createNewFile() throws IOException { } if (documentFile != null) { - lastModified = documentFile.lastModified(); + lastModified = fileSystemView.getCorrectedTime(documentFile.lastModified()); size = 0; readable = documentFile.canRead(); exists = true; From a2f55bbbcaefa6be288cbdbb4750239086802090 Mon Sep 17 00:00:00 2001 From: Laszlo Magyar Date: Sat, 5 Oct 2024 21:17:01 +0200 Subject: [PATCH 19/19] really fix merge conflict --- .../src/org/primftpd/filesystem/RoSafFtpFileSystemView.java | 2 +- .../src/org/primftpd/filesystem/RoSafSshFileSystemView.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFtpFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFtpFileSystemView.java index 445992df..83d7cc0b 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/RoSafFtpFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/RoSafFtpFileSystemView.java @@ -31,7 +31,7 @@ protected RoSafFtpFile createFile(ContentResolver contentResolver, Uri startUrl, } protected RoSafFtpFile createFileNonExistent(ContentResolver contentResolver, Uri startUrl, String name, String absPath, PftpdService pftpdService) { - return new RoSafFtpFile(contentResolver, startUrl, name, absPath, false, pftpdService, user); + return new RoSafFtpFile(contentResolver, startUrl, name, absPath, false, pftpdService, this, user); } @Override diff --git a/primitiveFTPd/src/org/primftpd/filesystem/RoSafSshFileSystemView.java b/primitiveFTPd/src/org/primftpd/filesystem/RoSafSshFileSystemView.java index 73ea14c7..09c80d03 100644 --- a/primitiveFTPd/src/org/primftpd/filesystem/RoSafSshFileSystemView.java +++ b/primitiveFTPd/src/org/primftpd/filesystem/RoSafSshFileSystemView.java @@ -29,7 +29,7 @@ protected RoSafSshFile createFile(ContentResolver contentResolver, Uri startUrl, @Override protected RoSafSshFile createFileNonExistent(ContentResolver contentResolver, Uri startUrl, String name, String absPath, PftpdService pftpdService) { - return new RoSafSshFile(contentResolver, startUrl, name, absPath, false, pftpdService, session); + return new RoSafSshFile(contentResolver, startUrl, name, absPath, false, pftpdService, this, session); } @Override