forked from I2P_Developers/i2p.i2p
i2psnark: Better handling of read-only i2psnark dir (ticket #1990)
Prevent add/create/remove/delete More handling of RuntimeException via Snark.fatal() in SnarkManager
This commit is contained in:
@ -1243,8 +1243,13 @@ public class Snark
|
|||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
if (storage != null) {
|
if (storage != null) {
|
||||||
try { storage.close(); } catch (IOException ioee) {}
|
try { storage.close(); } catch (IOException ioee) {}
|
||||||
|
// clear storage, we have a mess if we have non-null storage and null metainfo,
|
||||||
|
// as on restart, Storage.reopen() will throw an ioe
|
||||||
|
storage = null;
|
||||||
}
|
}
|
||||||
fatal("Could not check or create storage", ioe);
|
// TODO we're still in an inconsistent state, won't work if restarted
|
||||||
|
// (PeerState "disconnecting seed that connects to seeds"
|
||||||
|
fatal("Could not create data files", ioe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -731,7 +731,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
|
|||||||
return new SHA1Hash(ih);
|
return new SHA1Hash(ih);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** null to set initial defaults */
|
/** @param filename null to set initial defaults */
|
||||||
public void loadConfig(String filename) {
|
public void loadConfig(String filename) {
|
||||||
synchronized(_configLock) {
|
synchronized(_configLock) {
|
||||||
locked_loadConfig(filename);
|
locked_loadConfig(filename);
|
||||||
@ -896,7 +896,14 @@ public class SnarkManager implements CompleteListener, ClientApp {
|
|||||||
_util.setRatingsEnabled(Boolean.parseBoolean(_config.getProperty(PROP_RATINGS, "true")));
|
_util.setRatingsEnabled(Boolean.parseBoolean(_config.getProperty(PROP_RATINGS, "true")));
|
||||||
_util.setCommentsEnabled(Boolean.parseBoolean(_config.getProperty(PROP_COMMENTS, "true")));
|
_util.setCommentsEnabled(Boolean.parseBoolean(_config.getProperty(PROP_COMMENTS, "true")));
|
||||||
_util.setCommentsName(_config.getProperty(PROP_COMMENTS_NAME, ""));
|
_util.setCommentsName(_config.getProperty(PROP_COMMENTS_NAME, ""));
|
||||||
getDataDir().mkdirs();
|
File dd = getDataDir();
|
||||||
|
if (dd.isDirectory()) {
|
||||||
|
if (!dd.canWrite())
|
||||||
|
addMessage(_t("No write permissions for data directory") + ": " + dd);
|
||||||
|
} else {
|
||||||
|
if (!dd.mkdirs())
|
||||||
|
addMessage(_t("Data directory cannot be created") + ": " + dd);
|
||||||
|
}
|
||||||
initTrackerMap();
|
initTrackerMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1031,6 +1038,8 @@ public class SnarkManager implements CompleteListener, ClientApp {
|
|||||||
} else if (!dd.canRead()) {
|
} else if (!dd.canRead()) {
|
||||||
addMessage(_t("Unreadable") + ": " + dataDir);
|
addMessage(_t("Unreadable") + ": " + dataDir);
|
||||||
} else {
|
} else {
|
||||||
|
if (!dd.canWrite())
|
||||||
|
addMessage(_t("No write permissions for data directory") + ": " + dataDir);
|
||||||
changed = true;
|
changed = true;
|
||||||
interruptMonitor = true;
|
interruptMonitor = true;
|
||||||
_config.setProperty(PROP_DIR, dataDir);
|
_config.setProperty(PROP_DIR, dataDir);
|
||||||
@ -2640,6 +2649,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* If not connected, thread it, otherwise inline
|
* If not connected, thread it, otherwise inline
|
||||||
|
* @throws RuntimeException via Snark.fatal()
|
||||||
* @since 0.9.1
|
* @since 0.9.1
|
||||||
*/
|
*/
|
||||||
public void startTorrent(byte[] infoHash) {
|
public void startTorrent(byte[] infoHash) {
|
||||||
@ -2654,6 +2664,7 @@ public class SnarkManager implements CompleteListener, ClientApp {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* If not connected, thread it, otherwise inline
|
* If not connected, thread it, otherwise inline
|
||||||
|
* @throws RuntimeException via Snark.fatal()
|
||||||
* @since 0.9.23
|
* @since 0.9.23
|
||||||
*/
|
*/
|
||||||
public void startTorrent(Snark snark) {
|
public void startTorrent(Snark snark) {
|
||||||
@ -2701,17 +2712,14 @@ public class SnarkManager implements CompleteListener, ClientApp {
|
|||||||
private final Snark snark;
|
private final Snark snark;
|
||||||
public ThreadedStarter(Snark s) { snark = s; }
|
public ThreadedStarter(Snark s) { snark = s; }
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
|
||||||
run2();
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
_log.error("Error starting", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void run2() {
|
|
||||||
if (snark != null) {
|
if (snark != null) {
|
||||||
if (snark.isStopped())
|
if (snark.isStopped()) {
|
||||||
|
try {
|
||||||
snark.startTorrent();
|
snark.startTorrent();
|
||||||
|
} catch (RuntimeException re) {
|
||||||
|
// Snark.fatal() will log and call fatal() here for user message before throwing
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
startAll();
|
startAll();
|
||||||
}
|
}
|
||||||
@ -2724,8 +2732,13 @@ public class SnarkManager implements CompleteListener, ClientApp {
|
|||||||
*/
|
*/
|
||||||
private void startAll() {
|
private void startAll() {
|
||||||
for (Snark snark : _snarks.values()) {
|
for (Snark snark : _snarks.values()) {
|
||||||
if (snark.isStopped())
|
if (snark.isStopped()) {
|
||||||
|
try {
|
||||||
snark.startTorrent();
|
snark.startTorrent();
|
||||||
|
} catch (RuntimeException re) {
|
||||||
|
// Snark.fatal() will log and call fatal() here for user message before throwing
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -987,6 +987,11 @@ public class I2PSnarkServlet extends BasicServlet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File dd = _manager.getDataDir();
|
||||||
|
if (!dd.canWrite()) {
|
||||||
|
_manager.addMessage(_t("No write permissions for data directory") + ": " + dd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (newURL.startsWith("http://")) {
|
if (newURL.startsWith("http://")) {
|
||||||
FetchAndAdd fetch = new FetchAndAdd(_context, _manager, newURL, dir);
|
FetchAndAdd fetch = new FetchAndAdd(_context, _manager, newURL, dir);
|
||||||
_manager.addDownloader(fetch);
|
_manager.addDownloader(fetch);
|
||||||
@ -1045,12 +1050,18 @@ public class I2PSnarkServlet extends BasicServlet {
|
|||||||
_manager.addMessage(_t("Magnet deleted: {0}", name));
|
_manager.addMessage(_t("Magnet deleted: {0}", name));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_manager.stopTorrent(snark, true);
|
|
||||||
// should we delete the torrent file?
|
|
||||||
// yeah, need to, otherwise it'll get autoadded again (at the moment
|
|
||||||
File f = new File(name);
|
File f = new File(name);
|
||||||
f.delete();
|
File dd = _manager.getDataDir();
|
||||||
|
boolean canDelete = dd.canWrite() || !f.exists();
|
||||||
|
_manager.stopTorrent(snark, canDelete);
|
||||||
|
// TODO race here with the DirMonitor, could get re-added
|
||||||
|
if (f.delete()) {
|
||||||
_manager.addMessage(_t("Torrent file deleted: {0}", f.getAbsolutePath()));
|
_manager.addMessage(_t("Torrent file deleted: {0}", f.getAbsolutePath()));
|
||||||
|
} else if (f.exists()) {
|
||||||
|
if (!canDelete)
|
||||||
|
_manager.addMessage(_t("No write permissions for data directory") + ": " + dd);
|
||||||
|
_manager.addMessage(_t("Torrent file could not be deleted: {0}", f.getAbsolutePath()));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1074,10 +1085,19 @@ public class I2PSnarkServlet extends BasicServlet {
|
|||||||
_manager.addMessage(_t("Magnet deleted: {0}", name));
|
_manager.addMessage(_t("Magnet deleted: {0}", name));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_manager.stopTorrent(snark, true);
|
|
||||||
File f = new File(name);
|
File f = new File(name);
|
||||||
f.delete();
|
File dd = _manager.getDataDir();
|
||||||
|
boolean canDelete = dd.canWrite() || !f.exists();
|
||||||
|
_manager.stopTorrent(snark, canDelete);
|
||||||
|
// TODO race here with the DirMonitor, could get re-added
|
||||||
|
if (f.delete()) {
|
||||||
_manager.addMessage(_t("Torrent file deleted: {0}", f.getAbsolutePath()));
|
_manager.addMessage(_t("Torrent file deleted: {0}", f.getAbsolutePath()));
|
||||||
|
} else if (f.exists()) {
|
||||||
|
if (!canDelete)
|
||||||
|
_manager.addMessage(_t("No write permissions for data directory") + ": " + dd);
|
||||||
|
_manager.addMessage(_t("Torrent file could not be deleted: {0}", f.getAbsolutePath()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
Storage storage = snark.getStorage();
|
Storage storage = snark.getStorage();
|
||||||
if (storage == null)
|
if (storage == null)
|
||||||
break;
|
break;
|
||||||
@ -1178,6 +1198,11 @@ public class I2PSnarkServlet extends BasicServlet {
|
|||||||
// announceURL = announceURLOther;
|
// announceURL = announceURLOther;
|
||||||
|
|
||||||
if (baseFile.exists()) {
|
if (baseFile.exists()) {
|
||||||
|
File dd = _manager.getDataDir();
|
||||||
|
if (!dd.canWrite()) {
|
||||||
|
_manager.addMessage(_t("No write permissions for data directory") + ": " + dd);
|
||||||
|
return;
|
||||||
|
}
|
||||||
String torrentName = baseFile.getName();
|
String torrentName = baseFile.getName();
|
||||||
if (torrentName.toLowerCase(Locale.US).endsWith(".torrent")) {
|
if (torrentName.toLowerCase(Locale.US).endsWith(".torrent")) {
|
||||||
_manager.addMessage(_t("Cannot add a torrent ending in \".torrent\": {0}", baseFile.getAbsolutePath()));
|
_manager.addMessage(_t("Cannot add a torrent ending in \".torrent\": {0}", baseFile.getAbsolutePath()));
|
||||||
|
Reference in New Issue
Block a user