yaffs found a bug in the yaffs importer.
[yaffs2.git] / direct / python / yaffs_importer.py
1 import os
2 from yaffsfs import *
3 import sys
4 import ctypes
5
6
7 dir_in_snapshot=[]
8 files_in_snapshot=[]
9 symlinks_in_snapshot=[]
10 unknown_in_snapshot=[]
11 is_mount_in_snapshot=[]
12 def check_for_yaffs_errors(output):
13     if output<0:
14         ##error has happened
15         error=ctypes.c_int()
16         error=yaffs_get_error()
17         debug_message("error######################################",0)
18         debug_message(("error code", error),  0)
19
20 def debug_message(message, debug_level):
21     """notew that debug level 0 will always be printed"""
22     """level 0 error messages"""
23     """level 1 basic tasks are shown(creating, deleating,ect)"""
24     """level 2 all process are shown"""
25     if current_debug_level>=debug_level:
26         print message
27         
28 def join_paths(path1, path2):
29     new_path=path1
30     if path1[len(path1)-1]=="/"and path2[0]=="/":
31         new_path+=path2[1:]
32     elif path1[len(path1)-1]!="/"and path2[0]!="/":
33         new_path+="/"
34         new_path+=path2
35     else:
36         new_path+=path2
37     return new_path
38     
39 def subtract_paths(path1, path2):
40     if len(path1)>len(path2):
41         ##if the two paths are diretly subtractable
42         if path1[0:len (path2)-1]==path2:
43             new_path=path1[len(path2):]
44         elif path1[1:len (path2)-1]==path2:
45             new_path=path1[len(path2)+1:]
46         elif path1[1:len (path2)]==path2[1:]:
47             new_path=path1[len(path2)-1:]
48         else :
49             debug_message("error:could not subtract paths", 0)
50             debug_message( ("paths do not match:"+ path1+ "  "+path2), 0)
51             return 0
52         return new_path
53     else :
54         debug_message( ("cannot subtract path2(:", path2, ") from path1(", path1, ")because path 2 is too long"), 0)
55         return 0
56  
57     
58 def create_file(file):
59     debug_message( "\n \n \n", 2)
60     file_path=yaffs_root_dir_path+file["path"][len(path):]
61     debug_message( ("creating file:", file_path), 2)
62     debug_message (("mode", file["mode"]), 2)
63     debug_message("opening file",2)
64 #    yaffs_ls(file["path"])
65     output=yaffs_unlink(path)
66     print"unlinking", output
67     check_for_yaffs_errors(output)
68     current_handle=yaffs_open(file_path, yaffs_O_CREAT | yaffs_O_TRUNC| yaffs_O_RDWR, yaffs_S_IREAD | yaffs_S_IWRITE)  ##opens a file with mode set to write
69     debug_message(("current_handle", current_handle), 2)
70     data_file=open(file["path"], "r")
71     output=yaffs_lseek(current_handle, 0, 0)
72     if output==-1:
73         debug_message("error with yaffs lseeking", 2)
74         
75         check_for_yaffs_errors(output)
76     data_to_be_written= data_file.read()
77     
78     
79 #    debug_message( ("data to be saved########################################################################/n"+ data_to_be_written), 2)
80 #    debug_message("###########################################################################################",2)
81     length_of_file=len(data_to_be_written)
82     debug_message (("length of data to be written",length_of_file), 2) 
83     output=yaffs_write(current_handle,data_to_be_written , length_of_file)
84     if output>=0:
85         debug_message(( "writing file:", output), 2)
86     else :
87         debug_message(( "error writing file:", output), 0)
88         check_for_yaffs_errors(output)
89     output=yaffs_ftruncate(current_handle, length_of_file)
90     if output>=0:
91         debug_message(( "truncating file:", output), 2)
92     else :
93         debug_message(( "error truncating file:", output), 0)
94         check_for_yaffs_errors(output)
95     output=yaffs_close(current_handle)
96     if output>=0:
97         debug_message(( "closing file:", output), 2)
98     else :
99         debug_message(( "error closing file:", output), 0)
100         check_for_yaffs_errors(output)
101     ##changes the mode of the yaffs file to be the same as the scanned file
102     yaffs_chmod(file_path, file["mode"]);
103     if output>=0:
104         debug_message(( "chmoding file:", output), 2)
105     else :
106         debug_message(( "error chmoding file:", output), 0)
107         check_for_yaffs_errors(output)
108
109 def remove_file_from_path(path):
110     slash_id=[]
111     for i in range(0, len(path)):
112         if path[i]=="/":
113             slash_id.append(i)
114     new_path=path[:slash_id[len(slash_id)-1]]
115     debug_message( ("removed file from path", new_path), 2)
116     return new_path
117 def is_dir_hidden(dir):
118     """this code tests if a directory is hidden (has a ./<name> format) and returns true if it is hidden"""
119     slash_id=[]
120     for i in range(0, len(dir)):
121         if dir[i]=="/":
122             slash_id.append(i)
123
124     if dir[slash_id[len(slash_id)-1]+1]==".":
125         return True
126     else :
127         return False
128         
129 def scan_dir(path):
130     """this function scans all of the files and directories in a directory. The function then calls its self on any of the directories that it found. this causes it to build up a tree of all the files and directories """
131     global files_in_snapshot
132     global symlinks_in_snapshot
133     global search_hidden_directories
134     dir_in_current_dir=[]
135     if os.path.exists(path)==False:
136         debug_message ("error#############################",0)
137         debug_message (("path:", path, "  doesnot exist"), 0)
138         return 0
139     dir_snapshot=os.listdir(path)
140     for i in range(0, len(dir_snapshot)):
141
142         current_snapshot=os.path.join(path, dir_snapshot[i])
143         debug_message (("current snapshot:", current_snapshot), 2)
144         isDir=os.path.isdir(current_snapshot)
145         isFile=os.path.isfile(current_snapshot)
146         isLink=os.path.islink(current_snapshot)
147         isMount=os.path.ismount(current_snapshot)
148
149         stat=os.lstat(current_snapshot)
150         
151         ##note the order of these if and elif statemens is importaint since a file can be symbloic link and a file
152         if isDir:
153             if search_hidden_directories==True or (is_dir_hidden(current_snapshot) ==False or search_hidden_directories==True ) :
154 #                st_mode ##mode of the folder read/write ect
155                 dir_in_snapshot.append({"path":current_snapshot, "mode":stat.st_mode})
156                 dir_in_current_dir.append(current_snapshot)
157             else :
158                 debug_message( ("file is hidden so it is ingored", current_snapshot,), 1)
159         elif  isLink:
160
161             ##for some reason the os.readlink only gives the target link realative to the directory which the symbloic link is in. change this into a absolute path
162             x=current_snapshot
163             x=remove_file_from_path(x)
164             target=join_paths(x,os.readlink(current_snapshot) )
165             symlinks_in_snapshot.append({"path":current_snapshot, "target":target})
166         elif isFile:
167
168 #            stat.st_ino ##inode number
169 #            st_nlink ##number of hard links to this file
170 #            st_size ##size of file
171             files_in_snapshot.append({"path":current_snapshot, "inode": stat.st_ino, "size":stat.st_size, "num_of_hardlinks":stat.st_nlink, "mode":stat.st_mode})
172
173         elif isMount:
174             is_mount_in_snapshot.append(current_snapshot)
175         else:
176             unknown_in_snapshot.append(current_snapshot)
177             
178     for i in range(0, len(dir_in_current_dir)):
179         scan_dir(dir_in_current_dir[i])
180
181 def print_scanned_dir_list():
182     global files_in_snapshot
183     global symlinks_in_snapshot
184     print( "scanning dir", 2)
185
186
187     for i in range(0, len(files_in_snapshot)):
188         if files_in_snapshot[i]["num_of_hardlinks"]>1:
189             print "inode",files_in_snapshot[i]["inode"],"size",files_in_snapshot[i]["size"],"path:", files_in_snapshot[i]["path"], "    num of hard links",  files_in_snapshot[i]["num_of_hardlinks"] 
190
191         else :
192             print "inode",files_in_snapshot[i]["inode"],"size",files_in_snapshot[i]["size"],"path:", files_in_snapshot[i]["path"]
193 #        current_open_file=open(files_in_snapshot[i], "r")
194 #        #current_open_file.f.read(3)
195 #        lines_in_file=current_open_file.readlines()
196 #        #use for loop to write code into yaffs file
197 #        print "number of line of code:", len(lines_in_file)
198 #    print current_open_file
199     for i in range(0, len(symlinks_in_snapshot)):
200         print "symlinks in snapshot:", symlinks_in_snapshot[i]
201     for i in range(0, len(dir_in_snapshot)):
202         print "directories in snapshot:", dir_in_snapshot[i]
203     for i in range(0, len(unknown_in_snapshot)):
204         print "unknown objects in snapshot:", unknown_in_snapshot[i]
205
206 def copy_scanned_files_into_yaffs():
207     global files_in_snapshot
208     global symlinks_in_snapshot
209     global path
210 #########################################copy directories into yaffs so the files can be created in these directories
211     debug_message("making directories in yaffs", 1)
212     for i in range(0, len(dir_in_snapshot)):
213
214         
215         dir_path=join_paths(yaffs_root_dir_path,subtract_paths(dir_in_snapshot[i]["path"], path) )
216         output=yaffs_mkdir(dir_path,dir_in_snapshot[i]["mode"] )
217         debug_message(("made directory:", dir_path,   "  output", output), 1)
218         debug_message(("mode" ,dir_in_snapshot[i]["mode"]), 2)
219     
220     
221     
222 #########################################copy file into yaffs
223     debug_message("copying scanned files into yaffs", 1)
224     list=[]
225     inode_blacklist=[]
226
227     debug_message("files to be copyied into yaffs", 2)
228     for a in range(0, len(files_in_snapshot)):
229         debug_message(files_in_snapshot[a], 2)
230     debug_message("\n\n\n", 2)
231     for i in range(0, len(files_in_snapshot)):
232         list=[]
233         if files_in_snapshot[i]["num_of_hardlinks"]>1 and files_in_snapshot[i]["inode"] not in inode_blacklist :
234             debug_message("found a hard link", 2)
235             debug_message(("inode",files_in_snapshot[i]["inode"],"size",files_in_snapshot[i]["size"],"path:", files_in_snapshot[i]["path"], "    num of hard links",  files_in_snapshot[i]["num_of_hardlinks"] ), 2)
236             for a in range(0, len(files_in_snapshot) ) :
237                 if files_in_snapshot[a]["inode"] ==files_in_snapshot[i]["inode"]  :
238                     ##and os.path.isfile(files_in_snapshot[i])
239                     debug_message(("found this file which matches inode",files_in_snapshot[a]), 2) 
240                     list.append(files_in_snapshot[a])
241                     debug_message(("length of list", len(list)), 2)
242                 if len(list)==files_in_snapshot[i]["num_of_hardlinks"]:
243                     break
244             for a in range(0, len(list)):
245                 debug_message(list[a], 2)
246             ##add inode to blacklist. all of the indoes in the list should be the same.
247             inode_blacklist.append(list[0]["inode"])
248             ##create a file from the first hardlink.
249             create_file(list[0])
250             target_path=yaffs_root_dir_path+list[0]["path"][len(path):]
251             for i in range(1, len(list)):
252                 debug_message("creating_symlink", 2)
253                 debug_message(("target path", target_path), 2)
254                 hardlink_path=yaffs_root_dir_path+list[i]["path"][len(path):]
255                 debug_message(("hardlink path", hardlink_path), 2)
256                 output=yaffs_link(target_path,hardlink_path)
257                 debug_message(("creating hardlink:", list[i]["path"], "output:", output), 1)
258         elif files_in_snapshot[i]["inode"] not in inode_blacklist :
259             create_file(files_in_snapshot[i])
260
261
262 ############################copy symlinks into yaffs
263
264     for i in range(0, len(symlinks_in_snapshot)):
265         debug_message(("symlinks in snapshot:", symlinks_in_snapshot[i]), 2)
266         target_path=join_paths(yaffs_root_dir_path, subtract_paths(symlinks_in_snapshot[i]["target"],  path))
267         new_path=join_paths(yaffs_root_dir_path, subtract_paths(symlinks_in_snapshot[i]["path"], path))
268         output=yaffs_symlink(target_path, new_path)
269         debug_message(("created symlink",new_path , " > ", target_path, "  output:", output), 1)
270         ##yaffs_symlink(const YCHAR *oldpath, const YCHAR *newpath);
271    
272     
273     for i in range(0, len(unknown_in_snapshot)):
274         debug_message( ("unknown object in snapshot:", unknown_in_snapshot[i]), 0)
275         
276 def import_into_yaffs(file_path, yaffs_path="/yaffs2/", debug_level=1,  copy_hidden_dir=False,new_yaffs_trace_val=0 ):
277     global current_debug_level
278     global search_hidden_directories
279     global yaffs_root_dir_path
280     global path
281     
282     current_debug_level=debug_level
283     search_hidden_directories=copy_hidden_dir
284     yaffs_root_dir_path=yaffs_path
285     path=file_path
286     old_yaffs_trace_val=yaffs_get_trace()
287     yaffs_set_trace(new_yaffs_trace_val)
288     scan_dir(path)
289     copy_scanned_files_into_yaffs()
290     yaffs_set_trace(old_yaffs_trace_val)
291     
292     
293 if __name__=="__main__":
294     yaffs_StartUp()
295     yaffs_mount("/yaffs2/")
296     yaffs_set_trace(0)
297     absolute_path = os.path.abspath(os.path.curdir)
298     #print "absolute path:", absolute_path
299     current_debug_level=1
300     search_hidden_directories=True
301     yaffs_root_dir_path="/yaffs2/"
302     #print sys.argv
303     path=sys.argv[1]
304     for i in range(2, len(sys.argv)):
305         if sys.argv[i]=="-d":
306             current_debug_level=int( sys.argv[i+1])
307         if sys.argv[i]=="-ignore_hidden_directories":
308             search_hidden_directories=False
309 #
310 #
311 #    path="/home/timothy/work/yaffs/git/yaffs2"
312 #    path="/home/timothy/my_stuff/old_laptop/timothy/programming_lejos/"
313
314
315
316     scan_dir(path)
317     copy_scanned_files_into_yaffs()
318     #print_scanned_dir_list()
319
320     print"unmounting yaffs:", yaffs_unmount("/yaffs2/")