1 # -*- coding: utf-8 -*-
5 This module defines files utilities for lfm.
18 from utils
import get_shell_output2
21 ########################################################################
23 # File Type: dir, link to directory, link, nlink, char dev,
24 # block dev, fifo, socket, executable, file
25 (FTYPE_DIR
, FTYPE_LNK2DIR
, FTYPE_LNK
, FTYPE_NLNK
, FTYPE_CDEV
, FTYPE_BDEV
,
26 FTYPE_FIFO
, FTYPE_SOCKET
, FTYPE_EXE
, FTYPE_REG
) = xrange(10)
28 FILETYPES
= { FTYPE_DIR
: (os
.sep
, 'Directory'),
29 FTYPE_LNK2DIR
: ('~', 'Link to Directory'),
30 FTYPE_LNK
: ('@', 'Link'), FTYPE_NLNK
: ('!', 'No Link'),
31 FTYPE_CDEV
: ('-', 'Char Device'), FTYPE_BDEV
: ('+', 'Block Device'),
32 FTYPE_FIFO
: ('|', 'Fifo'), FTYPE_SOCKET
: ('#', 'Socket'),
33 FTYPE_EXE
: ('*', 'Executable'), FTYPE_REG
: (' ', 'File') }
35 (FT_TYPE
, FT_PERMS
, FT_OWNER
, FT_GROUP
, FT_SIZE
, FT_MTIME
) = xrange(6)
37 # Sort Type: None, byName, bySize, byDate, byType
38 (SORTTYPE_None
, SORTTYPE_byName
, SORTTYPE_byName_rev
, SORTTYPE_bySize
,
39 SORTTYPE_bySize_rev
, SORTTYPE_byDate
, SORTTYPE_byDate_rev
) = xrange(7)
42 ########################################################################
43 ##### general functions
44 # HACK: checks for st_rdev in stat_result, falling back to
45 # "ls -la %s" hack if Python before 2.2 or without st_rdev
47 os
.stat_result
.st_rdev
48 except AttributeError:
50 """'ls -la' to get mayor and minor number of devices"""
52 buf
= os
.popen('ls -la %s' % f
).read().split()
57 return int(buf
[4][:-1]), int(buf
[5])
59 # HACK: found 0xff.. encoded device numbers, ignore them...
63 """mayor and minor number of devices"""
64 r
= os
.stat(f
).st_rdev
65 return r
>> 8, r
& 255
69 """return the size of the directory or file via 'du -sk' command"""
71 buf
= get_shell_output2('du -sk \"%s\"' % f
)
73 return int(buf
.split()[0]) * 1024
78 def get_realpath(path
, filename
, filetype
):
79 """return absolute path or, if path is a link, pointed file"""
81 if filetype
in (FTYPE_LNK2DIR
, FTYPE_LNK
, FTYPE_NLNK
):
83 return '-> ' + os
.readlink(os
.path
.join(path
, filename
))
85 return os
.path
.join(path
, filename
)
87 return os
.path
.join(path
, filename
)
90 def get_linkpath(path
, filename
):
91 """return absolute path to the destination of a link"""
93 link_dest
= os
.readlink(os
.path
.join(path
, filename
))
94 return os
.path
.normpath(os
.path
.join(path
, link_dest
))
97 def join(directory
, f
):
98 if not os
.path
.isdir(directory
):
99 directory
= os
.path
.dirname(directory
)
100 return os
.path
.join(directory
, f
)
103 def __get_filetype(f
):
104 """get the type of the file. See listed types above"""
106 f
= os
.path
.abspath(f
)
107 lmode
= os
.lstat(f
)[stat
.ST_MODE
]
108 if stat
.S_ISDIR(lmode
):
110 if stat
.S_ISLNK(lmode
):
112 mode
= os
.stat(f
)[stat
.ST_MODE
]
116 if stat
.S_ISDIR(mode
):
120 if stat
.S_ISCHR(lmode
):
122 if stat
.S_ISBLK(lmode
):
124 if stat
.S_ISFIFO(lmode
):
126 if stat
.S_ISSOCK(lmode
):
128 if stat
.S_ISREG(lmode
) and (lmode
& 0111):
131 return FTYPE_REG
# if no other type, regular file
134 def get_fileinfo(f
, pardir_flag
= False, show_dirs_size
= False):
135 """return information about a file in next format:
136 (filetype, perms, owner, group, size, mtime)"""
139 typ
= __get_filetype(f
)
140 if typ
in (FTYPE_DIR
, FTYPE_LNK2DIR
) and not pardir_flag
and show_dirs_size
:
142 elif typ
in (FTYPE_CDEV
, FTYPE_BDEV
):
143 # HACK: it's too time consuming to calculate all files' rdevs
144 # in a directory, so we just calculate what we need
146 # maj_red, min_rdev = get_rdev(file)
149 size
= st
[stat
.ST_SIZE
]
151 owner
= pwd
.getpwuid(st
[stat
.ST_UID
])[0]
153 owner
= str(st
[stat
.ST_UID
])
155 group
= grp
.getgrgid(st
[stat
.ST_GID
])[0]
157 group
= str(st
[stat
.ST_GID
])
158 return (typ
, stat
.S_IMODE(st
[stat
.ST_MODE
]), owner
, group
,
159 size
, st
[stat
.ST_MTIME
])
163 permis
= ['x', 'w', 'r']
167 perms
[i
] = permis
[(8-i
) % 3]
174 return ''.join(perms
)
177 def get_fileinfo_dict(path
, filename
, filevalues
):
178 """return a dict with file information"""
181 res
['filename'] = filename
182 typ
= filevalues
[FT_TYPE
]
183 res
['type_chr'] = FILETYPES
[typ
][0]
184 if typ
== (FTYPE_CDEV
, FTYPE_BDEV
):
185 # HACK: it's too time consuming to calculate all files' rdevs
186 # in a directory, so we just calculate needed ones here
188 maj_rdev
, min_rdev
= get_rdev(os
.path
.join(path
, filename
))
190 res
['maj_rdev'] = maj_rdev
191 res
['min_rdev'] = min_rdev
194 size
= filevalues
[FT_SIZE
]
195 if size
>= 1000000000L:
196 size
= str(size
/(1024*1024)) + 'M'
197 elif size
>= 10000000L:
198 size
= str(size
/1024) + 'K'
205 res
['perms'] = perms2str(filevalues
[1])
206 res
['owner'] = filevalues
[FT_OWNER
]
207 res
['group'] = filevalues
[FT_GROUP
]
208 if -15552000 < (time
.time() - filevalues
[FT_MTIME
]) < 15552000:
209 # filedate < 6 months from now, past or future
210 mtime
= time
.strftime('%a %b %d %H:%M', time
.localtime(filevalues
[FT_MTIME
]))
211 mtime2
= time
.strftime('%d %b %H:%M', time
.localtime(filevalues
[FT_MTIME
]))
213 mtime
= time
.strftime('%a %d %b %Y', time
.localtime(filevalues
[FT_MTIME
]))
214 mtime2
= time
.strftime('%d %b %Y', time
.localtime(filevalues
[FT_MTIME
]))
216 res
['mtime2'] = mtime2
220 def get_dir(path
, show_dotfiles
= 1):
221 """return a dict whose elements are formed by file name as key
222 and a (filetype, perms, owner, group, size, mtime) tuple as value"""
224 path
= os
.path
.normpath(path
)
227 files_dict
[os
.pardir
] = get_fileinfo(os
.path
.dirname(path
), 1)
228 files_list
= os
.listdir(path
)
229 if not show_dotfiles
:
230 files_list
= [f
for f
in files_list
if f
[0] != '.']
232 files_dict
[f
] = get_fileinfo(os
.path
.join(path
, f
))
233 return len(files_dict
), files_dict
237 """get a list with the users defined in the system"""
238 return [e
[0] for e
in pwd
.getpwall()]
241 def get_user_fullname(user
):
242 """return the fullname of an user"""
244 return pwd
.getpwnam(user
)[4]
246 return '<unknown user name>'
250 """get a list with the groups defined in the system"""
251 return [e
[0] for e
in grp
.getgrall()]
254 def set_perms(f
, perms
):
255 """set permissions to a file"""
259 ps
+= 1 * 8 ** int(i
/ 3)
261 ps
+= 2 * 8 ** int(i
/ 3)
263 ps
+= 4 * 8 ** int(i
/ 3)
264 elif p
== 't' and i
== 0:
266 elif p
== 's' and (i
== 6 or i
== 3):
274 except (IOError, os
.error
), (errno
, strerror
):
275 return (strerror
, errno
)
278 def set_owner_group(f
, owner
, group
):
279 """set owner and group to a file"""
281 owner_n
= pwd
.getpwnam(owner
)[2]
285 group_n
= grp
.getgrnam(group
)[2]
289 os
.chown(f
, owner_n
, group_n
)
290 except (IOError, os
.error
), (errno
, strerror
):
291 return (strerror
, errno
)
294 """return a list containing the info returned by 'df -k', i.e,
295 file systems size and occupation, in Mb. And the filesystem type:
296 [dev, size, used, available, use%, mount point, fs type]"""
299 buf
= os
.popen('df -k').readlines()
300 except (IOError, os
.error
), (errno
, strerror
):
301 return (strerror
, errno
)
308 e
[1] = str(int(e
[1]) / 1024)
309 e
[2] = str(int(e
[2]) / 1024)
310 e
[3] = str(int(e
[3]) / 1024)
317 e
.append(str(int(t
[0]) / 1024))
318 e
.append(str(int(t
[1]) / 1024))
319 e
.append(str(int(t
[2]) / 1024))
326 # get filesystems type
327 if sys
.platform
[:5] == 'linux':
328 es
= open('/etc/fstab').readlines()
330 elif sys
.platform
[:5] == 'sunos':
331 es
= open('/etc/vfstab').readlines()
337 if e
.find(f
[5]) != -1:
338 f
.append(e
.split()[fstype_pos
])
345 ########################################################################
348 return tempfile
.mkstemp()[1]
351 return tempfile
.mkdtemp()
354 ########################################################################
356 def __do_sort(f_dict
, sortmode
, sort_mix_cases
):
357 def __move_pardir_to_top(names
):
358 if names
.count(os
.pardir
) != 0:
359 names
.remove(os
.pardir
)
360 names
.insert(0, os
.pardir
)
363 if sortmode
== SORTTYPE_None
:
364 names
= f_dict
.keys()
365 return __move_pardir_to_top(f_dict
)
367 if sortmode
in (SORTTYPE_byName
, SORTTYPE_byName_rev
):
369 mycmp
= lambda a
, b
: cmp(a
.lower(), b
.lower())
372 names
= f_dict
.keys()
373 names
.sort(cmp=mycmp
)
374 if sortmode
== SORTTYPE_byName_rev
:
376 return __move_pardir_to_top(names
)
379 for k
in f_dict
.keys():
380 if sortmode
in (SORTTYPE_bySize
, SORTTYPE_bySize_rev
):
381 size
= f_dict
[k
][FT_SIZE
]
382 while mydict
.has_key(size
): # can't be 2 entries with same key
385 elif sortmode
in (SORTTYPE_byDate
, SORTTYPE_byDate_rev
):
386 tim
= f_dict
[k
][FT_MTIME
]
387 while mydict
.has_key(tim
): # can't be 2 entries with same key
392 values
= mydict
.keys()
394 names
= [mydict
[v
] for v
in values
]
395 if sortmode
in (SORTTYPE_bySize_rev
, SORTTYPE_byDate_rev
):
397 return __move_pardir_to_top(names
)
400 def sort_dir(files_dict
, sortmode
, sort_mix_dirs
, sort_mix_cases
):
401 """return an array of files which are sorted by mode"""
403 # separate directories and files
408 for k
, v
in files_dict
.items():
409 if v
[FT_TYPE
] in (FTYPE_DIR
, FTYPE_LNK2DIR
):
415 d1
= __do_sort(d
, sortmode
, sort_mix_cases
)
418 d2
= __do_sort(f
, sortmode
, sort_mix_cases
)
423 ########################################################################
425 def complete(entrypath
, panelpath
):
428 elif entrypath
[0] == os
.sep
:
431 path
= os
.path
.join(panelpath
, entrypath
)
433 if os
.path
.isdir(path
):
435 fs
= os
.listdir(path
)
437 basedir
= os
.path
.dirname(path
)
438 start
= os
.path
.basename(path
)
440 entries
= os
.listdir(basedir
)
443 fs
= [f
for f
in entries
if f
.find(start
, 0) == 0]
444 # sort files with dirs first
447 if os
.path
.isdir(os
.path
.join(basedir
, f
)):
448 d1
.append(f
+ os
.sep
)
457 ########################################################################
460 def do_create_link(pointto
, link
):
461 os
.symlink(pointto
, link
)
464 def modify_link(pointto
, linkname
):
467 do_create_link(pointto
, linkname
)
468 except (IOError, os
.error
), (errno
, strerror
):
469 return (strerror
, errno
)
472 def create_link(pointto
, linkname
):
474 do_create_link(pointto
, linkname
)
475 except (IOError, os
.error
), (errno
, strerror
):
476 return (strerror
, errno
)
480 def do_copy(source
, dest
):
483 if os
.path
.islink(source
):
484 dest
= os
.path
.join(os
.path
.dirname(dest
), os
.path
.basename(source
))
486 do_create_link(os
.readlink(source
), dest
)
487 except (IOError, os
.error
), (errno
, strerror
):
488 return (strerror
, errno
)
489 elif os
.path
.isdir(source
):
492 except (IOError, os
.error
), (errno
, strerror
):
493 pass # don't return if directory exists
495 # # copy mode, times, owner and group
496 # st = os.lstat(source)
497 # os.chown(dest, st[stat.ST_UID], st[stat.ST_GID])
498 # shutil.copymode(source, dest)
499 # shutil.copystat(source, dest)
501 for f
in os
.listdir(source
):
502 do_copy(os
.path
.join(source
, f
), os
.path
.join(dest
, f
))
504 raise IOError, (0, "Source and destination are the same file")
506 shutil
.copy2(source
, dest
)
509 def copy(f
, path
, destdir
, check_fileexists
= 1):
510 """ copy file / dir to destdir"""
512 fullpath
= os
.path
.join(path
, f
)
513 if destdir
[0] != os
.sep
:
514 destdir
= os
.path
.join(path
, destdir
)
515 if os
.path
.isdir(destdir
):
516 destdir
= os
.path
.join(destdir
, f
)
517 if os
.path
.exists(destdir
) and check_fileexists
:
518 return os
.path
.basename(destdir
)
520 do_copy(fullpath
, destdir
)
521 except (IOError, os
.error
), (errno
, strerror
):
522 return (strerror
, errno
)
526 def move(f
, path
, destdir
, check_fileexists
= 1):
527 """delete file / dir"""
529 fullpath
= os
.path
.join(path
, f
)
530 if destdir
[0] != os
.sep
:
531 destdir
= os
.path
.join(path
, destdir
)
532 if os
.path
.isdir(destdir
):
533 destdir
= os
.path
.join(destdir
, f
)
534 if os
.path
.exists(destdir
) and check_fileexists
:
535 return os
.path
.basename(destdir
)
536 if os
.path
.dirname(fullpath
) == os
.path
.dirname(destdir
):
538 os
.rename(fullpath
, destdir
)
539 except (IOError, os
.error
), (errno
, strerror
):
540 return (strerror
, errno
)
543 do_copy(fullpath
, destdir
)
544 except (IOError, os
.error
), (errno
, strerror
):
547 except (IOError, os
.error
), (errno
, strerror
):
548 return (strerror
, errno
)
550 return (strerror
, errno
)
554 except (IOError, os
.error
), (errno
, strerror
):
555 return (strerror
, errno
)
560 if os
.path
.islink(f
):
562 elif os
.path
.isdir(f
):
563 for f2
in os
.listdir(f
):
564 do_delete(os
.path
.join(f
, f2
))
571 """delete file / dir"""
573 fullpath
= os
.path
.join(path
, f
)
576 except (IOError, os
.error
), (errno
, strerror
):
577 return (strerror
, errno
)
581 def mkdir(path
, newdir
):
582 """create directory"""
584 fullpath
= os
.path
.join(path
, newdir
)
586 os
.makedirs(fullpath
)
587 except (IOError, os
.error
), (errno
, strerror
):
588 return (strerror
, errno
)
591 ########################################################################