Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Android bug on FAT32/exFAT SD card time resolution and mtime caching #360

Merged
merged 19 commits into from
Oct 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions primitiveFTPd/src/org/primftpd/filesystem/FsFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
public abstract class FsFile<T> extends AbstractFile {

protected final File file;
protected final FsFileSystemView fileSystemView;
protected final boolean injectedDirectory;

private final static Map<String, String[]> DIRECTORY_INJECTIONS;
Expand All @@ -46,20 +47,21 @@ public abstract class FsFile<T> extends AbstractFile {
}
}
INJECTIONS_AND_CHILDREN = Collections.unmodifiableSet(tmp);
}
}

public FsFile(File file, PftpdService pftpdService) {
public FsFile(File file, PftpdService pftpdService, FsFileSystemView fileSystemView) {
super(
file.getAbsolutePath(),
file.getName(),
file.lastModified(),
fileSystemView.getCorrectedTime(file.getAbsolutePath(), file.lastModified()),
file.length(),
file.canRead(),
file.exists(),
file.isDirectory(),
pftpdService);
this.file = file;
this.name = file.getName();
this.fileSystemView = fileSystemView;
this.injectedDirectory = file.isDirectory() && INJECTIONS_AND_CHILDREN.contains(file.getAbsolutePath());
}

Expand Down Expand Up @@ -144,7 +146,8 @@ public boolean isRemovable() {

public boolean setLastModified(long time) {
logger.trace("[{}] setLastModified({})", name, Long.valueOf(time));
return file.setLastModified(time);
long correctedTime = fileSystemView.getCorrectedTime(absPath, time);
return file.setLastModified(correctedTime);
}

public boolean mkdir() {
Expand Down
14 changes: 13 additions & 1 deletion primitiveFTPd/src/org/primftpd/filesystem/FsFileSystemView.java
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -9,16 +12,25 @@
public abstract class FsFileSystemView<T extends FsFile<X>, 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;
}

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) {
logger.trace("getFile({})", file);
String abs = absolute(file);
Expand Down
10 changes: 7 additions & 3 deletions primitiveFTPd/src/org/primftpd/filesystem/FsFtpFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,23 @@
public class FsFtpFile extends FsFile<FtpFile> implements FtpFile {
private final User user;

public FsFtpFile(File file, PftpdService pftpdService, User user) {
super(file, pftpdService);
public FsFtpFile(File file, PftpdService pftpdService, FsFtpFileSystemView fileSystemView, User user) {
super(file, pftpdService, fileSystemView);
this.user = user;
}

private FsFtpFileSystemView getFileSystemView() {
return (FsFtpFileSystemView)fileSystemView;
}

@Override
public String getClientIp() {
return FtpUtils.getClientIp(user);
}

@Override
protected FtpFile createFile(File file, PftpdService pftpdService) {
return new FsFtpFile(file, pftpdService, user);
return new FsFtpFile(file, pftpdService, getFileSystemView(), user);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -14,16 +17,16 @@ public class FsFtpFileSystemView extends FsFileSystemView<FsFtpFile, FtpFile> 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;
}

@Override
protected FsFtpFile createFile(File file, PftpdService pftpdService) {
return new FsFtpFile(file, pftpdService, user);
return new FsFtpFile(file, pftpdService, this, user);
}

@Override
Expand Down
12 changes: 8 additions & 4 deletions primitiveFTPd/src/org/primftpd/filesystem/FsSshFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,23 @@
public class FsSshFile extends FsFile<SshFile> implements SshFile {
private final Session session;

public FsSshFile(File file, PftpdService pftpdService, Session session) {
super(file, pftpdService);
public FsSshFile(File file, PftpdService pftpdService, FsSshFileSystemView fileSystemView, Session session) {
super(file, pftpdService, fileSystemView);
this.session = session;
}

private FsSshFileSystemView getFileSystemView() {
return (FsSshFileSystemView)fileSystemView;
}

@Override
public String getClientIp() {
return SshUtils.getClientIp(session);
}

@Override
protected SshFile createFile(File file, PftpdService pftpdService) {
return new FsSshFile(file, pftpdService, session);
return new FsSshFile(file, pftpdService, getFileSystemView(), session);
}

@Override
Expand All @@ -46,7 +50,7 @@ public boolean create() throws IOException {
@Override
public SshFile getParentFile() {
logger.trace("[{}] getParentFile()", name);
return new FsSshFile(file.getParentFile(), pftpdService, session);
return new FsSshFile(file.getParentFile(), pftpdService, getFileSystemView(), session);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -12,15 +15,15 @@ public class FsSshFileSystemView extends FsFileSystemView<FsSshFile, SshFile> 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, this, session);
}

@Override
Expand Down
15 changes: 11 additions & 4 deletions primitiveFTPd/src/org/primftpd/filesystem/RoSafFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public abstract class RoSafFile<T> extends AbstractFile {

private final ContentResolver contentResolver;
protected final Uri startUrl;
protected final RoSafFileSystemView fileSystemView;

private String documentId;
private boolean writable;
Expand All @@ -40,7 +41,8 @@ public RoSafFile(
ContentResolver contentResolver,
Uri startUrl,
String absPath,
PftpdService pftpdService) {
PftpdService pftpdService,
RoSafFileSystemView fileSystemView) {
// this c-tor is to be used for start directory
super(
absPath,
Expand All @@ -54,6 +56,7 @@ public RoSafFile(
logger.trace(" c-tor 1");
this.contentResolver = contentResolver;
this.startUrl = startUrl;
this.fileSystemView = fileSystemView;

try {
Cursor cursor = contentResolver.query(
Expand Down Expand Up @@ -85,7 +88,8 @@ public RoSafFile(
String docId,
String absPath,
boolean exists,
PftpdService pftpdService) {
PftpdService pftpdService,
RoSafFileSystemView fileSystemView) {
// this c-tor is to be used for FileSystemView.getFile()
super(
absPath,
Expand All @@ -99,6 +103,7 @@ public RoSafFile(
logger.trace(" c-tor 2");
this.contentResolver = contentResolver;
this.startUrl = startUrl;
this.fileSystemView = fileSystemView;

if (exists) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Expand Down Expand Up @@ -130,7 +135,8 @@ public RoSafFile(
Uri startUrl,
Cursor cursor,
String absPath,
PftpdService pftpdService) {
PftpdService pftpdService,
RoSafFileSystemView fileSystemView) {
// this c-tor is to be used by listFiles()
super(
absPath,
Expand All @@ -144,13 +150,14 @@ public RoSafFile(
logger.trace(" c-tor 3");
this.contentResolver = contentResolver;
this.startUrl = startUrl;
this.fileSystemView = fileSystemView;
initByCursor(cursor);
}

private void initByCursor(Cursor cursor) {
documentId = cursor.getString(0);
name = cursor.getString(1);
lastModified = cursor.getLong(2);
lastModified = fileSystemView.getCorrectedTime(cursor.getLong(2));
size = cursor.getLong(3);

logger.trace(" initByCursor, doc id: {}, name: {}", documentId, name);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ public abstract class RoSafFileSystemView<T extends RoSafFile<X>, 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);
Expand All @@ -47,6 +49,10 @@ protected abstract T createFileNonExistent(
String absPath,
PftpdService pftpdService);

public long getCorrectedTime(long time) {
return (time / timeResolution) * timeResolution;
}

public T getFile(String file) {
logger.trace("getFile({}), startUrl: {}", file, startUrl);

Expand Down
15 changes: 11 additions & 4 deletions primitiveFTPd/src/org/primftpd/filesystem/RoSafFtpFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ public RoSafFtpFile(
Uri startUrl,
String absPath,
PftpdService pftpdService,
RoSafFtpFileSystemView fileSystemView,
User user) {
super(contentResolver, startUrl, absPath, pftpdService);
super(contentResolver, startUrl, absPath, pftpdService, fileSystemView);
this.user = user;
}

Expand All @@ -29,8 +30,9 @@ public RoSafFtpFile(
String absPath,
boolean exists,
PftpdService pftpdService,
RoSafFtpFileSystemView fileSystemView,
User user) {
super(contentResolver, startUrl, docId, absPath, exists, pftpdService);
super(contentResolver, startUrl, docId, absPath, exists, pftpdService, fileSystemView);
this.user = user;
}

Expand All @@ -40,19 +42,24 @@ public RoSafFtpFile(
Cursor cursor,
String absPath,
PftpdService pftpdService,
RoSafFtpFileSystemView fileSystemView,
User user) {
super(contentResolver, startUrl, cursor, absPath, pftpdService);
super(contentResolver, startUrl, cursor, absPath, pftpdService, fileSystemView);
this.user = user;
}

private RoSafFtpFileSystemView getFileSystemView() {
return (RoSafFtpFileSystemView)fileSystemView;
}

@Override
protected FtpFile createFile(
ContentResolver contentResolver,
Uri startUrl,
Cursor cursor,
String absPath,
PftpdService pftpdService) {
return new RoSafFtpFile(contentResolver, startUrl, cursor, absPath, pftpdService, user);
return new RoSafFtpFile(contentResolver, startUrl, cursor, absPath, pftpdService, getFileSystemView(), user);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,16 @@ 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, 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, 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) {
return new RoSafFtpFile(contentResolver, startUrl, name, absPath, false, pftpdService, user);
return new RoSafFtpFile(contentResolver, startUrl, name, absPath, false, pftpdService, this, user);
}

@Override
Expand Down
Loading