dc72785cd46a4670ec7a4542921647bf473e9d48
[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     """level 3 shows minor tasks such as join_paths, ect"""
26     """level 4 is used for bug hunting and shows each step in detail"""
27     if current_debug_level>=debug_level:
28 #        for i in range(0, len(message)):
29 #            print message, 
30 #        print"\n \n \n"
31         print message
32 def join_paths(path1, path2):
33     new_path=path1
34     if path1[len(path1)-1]=="/"and path2[0]=="/":
35         new_path+=path2[1:]
36     elif path1[len(path1)-1]!="/"and path2[0]!="/":
37         new_path+="/"
38         new_path+=path2
39     else:
40         new_path+=path2
41     
42     debug_message(("adding path ", path1, " to ",  path2, " resulting path: ", new_path), 3)
43     return new_path
44     
45 def subtract_paths(path1, path2):
46     if len(path1)>len(path2):
47         if path1[len(path1)-1]!="/":
48             path1 +="/"
49         if path2[len(path2)-1]!="/":
50             path2 += "/"
51         debug_message("the two path1 is longer than path2 and can therefore be subtracted.", 4)
52         ##if the two paths are diretly subtractable
53         if path1[0:len (path2)-1]==path2:
54             debug_message("the two paths are direcly subtractable", 4)
55             new_path=path1[len(path2):]
56         elif path1[1:len (path2)-1]==path2:
57             debug_message("the path1 has one more charecter at the begining. assuming that the first chareter is a slash", 4)##fix this assumption.
58             new_path=path1[len(path2)+1:]
59         elif path1[1:len (path2)]==path2[1:]:
60             debug_message("the path2 has one more charecter at the begining. assuming that the first chareter is a slash", 4)##fix this assumption.
61
62             new_path=path1[len(path2)-1:]
63         else :
64             debug_message("error:could not subtract paths", 0)
65             debug_message( ("paths do not match:"+ path1+ "  "+path2), 0)
66             return 0
67     else :
68         debug_message( ("cannot subtract path2(:", path2, ") from path1(", path1, ")because path 2 is too long"), 0)
69         
70         return 0
71     debug_message(("subtracting paths ", path2, " from ",  path1, " resulting path: ", new_path), 3)
72     return new_path
73     
74 def create_file(file):
75     debug_message( "\n \n \n", 2)
76     file_path= join_paths(yaffs_root_dir_path, file["path"][len(path):])
77     debug_message( ("creating file:", file_path), 2)
78     debug_message (("mode", file["mode"]), 2)
79     debug_message("opening file",2)
80 #    yaffs_ls(file["path"])
81
82     ##if there is already a file in yaffs then remove the file . this is to prevent yaffs from opening a nd writing to a read only file
83     if yaffs_access(file_path, 0)==0:##the 0 means does it exist. 
84         debug_message ("file already exists in yaffs", 2)
85         output=yaffs_unlink(file_path)
86         debug_message(("unlinking", file_path, output), 2)
87         check_for_yaffs_errors(output)
88     
89     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
90     debug_message(("current_handle", current_handle), 2)
91     data_file=open(file["path"], "r")
92     output=yaffs_lseek(current_handle, 0, 0)
93     if output==-1:
94         debug_message("error with yaffs lseeking", 2)
95         
96         check_for_yaffs_errors(output)
97     data_to_be_written= data_file.read()
98     
99     
100     length_of_file=len(data_to_be_written)
101     debug_message (("length of data to be written",length_of_file), 2) 
102     output=yaffs_write(current_handle,data_to_be_written , length_of_file)
103     if output>=0:
104         debug_message(( "writing file:", output), 2)
105     else :
106         debug_message(( "error writing file:", output), 0)
107         check_for_yaffs_errors(output)
108     output=yaffs_ftruncate(current_handle, length_of_file)
109     if output>=0:
110         debug_message(( "truncating file:", output), 2)
111     else :
112         debug_message(( "error truncating file:", output), 0)
113         check_for_yaffs_errors(output)
114     output=yaffs_close(current_handle)
115     if output>=0:
116         debug_message(( "closing file:", output), 2)
117     else :
118         debug_message(( "error closing file:", output), 0)
119         check_for_yaffs_errors(output)
120     ##changes the mode of the yaffs file to be the same as the scanned file
121     yaffs_chmod(file_path, file["mode"]);
122     if output>=0:
123         debug_message(( "chmoding file:", output), 2)
124     else :
125         debug_message(( "error chmoding file:", output), 0)
126         check_for_yaffs_errors(output)
127
128
129
130 def create_dir(dir, scanned_path, yaffs_path):
131     debug_message( "\n \n \n", 2)
132     absolute_dir_path=join_paths(yaffs_path, subtract_paths(dir["path"],scanned_path)) 
133     debug_message( ("creating dir:", absolute_dir_path), 2)
134     debug_message (("mode(in octal", oct(dir["mode"])), 2)
135
136
137     ##if there is already a dir in yaffs then remove the dir . this is to clean the yaffs folder if it already exists.
138     if yaffs_access(absolute_dir_path, 0)==0:##the 0 means does it exist. 
139         debug_message ("folder already exists in yaffs", 2)
140         output=yaffs_unlink(absolute_dir_path)
141         debug_message(("unlinking", absolute_dir_path, output), 2)
142         check_for_yaffs_errors(output)
143         
144     ##shis is a bug in yaffs which will not make a dir if there is a slash on the end
145     if absolute_dir_path[len(absolute_dir_path)-1]=="/":
146         absolute_dir_path=absolute_dir_path[0:len(absolute_dir_path)-1]
147         debug_message (("path has slash on the end. removing slash new path is:",absolute_dir_path) , 4)
148         
149     output=yaffs_mkdir(absolute_dir_path, dir["mode"] )
150     if output>=0:
151         debug_message(( "creating dir:", output), 2)
152     else :
153         debug_message(( "error creating dir:", output), 0)
154         check_for_yaffs_errors(output)
155     
156     
157
158
159 def remove_file_from_path(path):
160     slash_id=[]
161     for i in range(0, len(path)):
162         if path[i]=="/":
163             slash_id.append(i)
164     new_path=path[:slash_id[len(slash_id)-1]]
165     debug_message( ("removed file from path", new_path), 2)
166     return new_path
167     
168 def is_dir_hidden(dir):
169     """this code tests if a directory is hidden (has a ./<name> format) and returns true if it is hidden"""
170     slash_id=[]
171     for i in range(0, len(dir)):
172         if dir[i]=="/":
173             slash_id.append(i)
174
175     if dir[slash_id[len(slash_id)-1]+1]==".":
176         return True
177     else :
178         return False
179     
180 def scan_dir(path, search_hidden_directories=True, ):
181     """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 """
182     files_in_snapshot=[]
183     symlinks_in_snapshot=[]
184     dir_in_snapshot=[]
185     dir_in_current_dir=[]
186     unknown_in_snapshot=[]
187     if os.path.exists(path)==False:
188         debug_message ("error#############################",0)
189         debug_message (("path:", path, "  doesnot exist"), 0)
190         return 0
191     dir_snapshot=os.listdir(path)
192     for i in range(0, len(dir_snapshot)):
193
194         current_snapshot=os.path.join(path, dir_snapshot[i])
195         debug_message (("current snapshot:", current_snapshot), 2)
196         isDir=os.path.isdir(current_snapshot)
197         isFile=os.path.isfile(current_snapshot)
198         isLink=os.path.islink(current_snapshot)
199         isMount=os.path.ismount(current_snapshot)
200
201         stat=os.lstat(current_snapshot)
202         
203         ##note the order of these if and elif statemens is importaint since a file can be symbloic link and a file
204         if isDir:
205             if search_hidden_directories==True or (is_dir_hidden(current_snapshot) ==False or search_hidden_directories==True ) :
206 #                st_mode ##mode of the folder read/write ect
207                 dir_in_snapshot.append({"path":current_snapshot, "mode":stat.st_mode})
208                 dir_in_current_dir.append(current_snapshot)
209             else :
210                 debug_message( ("file is hidden so it is ingored", current_snapshot,), 1)
211         elif  isLink:
212
213             ##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
214             x=current_snapshot
215             x=remove_file_from_path(x)
216             target=join_paths(x,os.readlink(current_snapshot) )
217             symlinks_in_snapshot.append({"path":current_snapshot, "target":target})
218         elif isFile:
219
220 #            stat.st_ino ##inode number
221 #            st_nlink ##number of hard links to this file
222 #            st_size ##size of file
223             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})
224
225 #        elif isMount:
226 #            is_mount_in_snapshot.append(current_snapshot)
227         else:
228             unknown_in_snapshot.append(current_snapshot)
229             
230     for i in range(0, len(dir_in_current_dir)):
231         scan_dir(dir_in_current_dir[i])
232     return (files_in_snapshot, dir_in_snapshot, symlinks_in_snapshot, unknown_in_snapshot)
233 ##
234 ##def print_scanned_dir_list():
235 ##    global files_in_snapshot
236 ##    global symlinks_in_snapshot
237 ##    print( "scanning dir", 2)
238 ##
239 ##
240 ##    for i in range(0, len(files_in_snapshot)):
241 ##        if files_in_snapshot[i]["num_of_hardlinks"]>1:
242 ##            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"] 
243 ##
244 ##        else :
245 ##            print "inode",files_in_snapshot[i]["inode"],"size",files_in_snapshot[i]["size"],"path:", files_in_snapshot[i]["path"]
246 ###        current_open_file=open(files_in_snapshot[i], "r")
247 ###        #current_open_file.f.read(3)
248 ###        lines_in_file=current_open_file.readlines()
249 ###        #use for loop to write code into yaffs file
250 ###        print "number of line of code:", len(lines_in_file)
251 ###    print current_open_file
252 ##    for i in range(0, len(symlinks_in_snapshot)):
253 ##        print "symlinks in snapshot:", symlinks_in_snapshot[i]
254 ##    for i in range(0, len(dir_in_snapshot)):
255 ##        print "directories in snapshot:", dir_in_snapshot[i]
256 ##    for i in range(0, len(unknown_in_snapshot)):
257 ##        print "unknown objects in snapshot:", unknown_in_snapshot[i]
258 ##
259
260
261 def copy_scanned_files_into_yaffs(files_in_snapshot, dir_in_snapshot,  symlinks_in_snapshot, unknown_in_snapshot,   path, yaffs_root_dir_path="/yaffs2/", yaffs_mount_point_path="/yaffs2/" ):
262 #files_in_snapshot, dir_in_snapshot, symlinks_in_snapshot, unknown_in_snapshot
263 #########################################copy directories into yaffs so the files can be created in these directories
264     debug_message("making directories in yaffs", 1)
265     if yaffs_root_dir_path!=yaffs_mount_point_path:
266         slash_id=[]
267         debug_message("making directories to the place in yaffs where the directories will copied to", 2)
268         root_branch_path=subtract_paths(yaffs_root_dir_path, yaffs_mount_point_path)
269         for i in range(0, len(root_branch_path)):
270
271             if root_branch_path[i]=="/" and i != 0:
272                slash_id.append(i)
273         debug_message(("slash_id", slash_id),4) 
274         for i in range(0, len(slash_id)):
275             create_dir({"path":root_branch_path[:slash_id[i]], "mode": yaffs_S_IREAD | yaffs_S_IWRITE}, "/", yaffs_mount_point_path) 
276     
277     for i in range(0, len(dir_in_snapshot)):
278         create_dir(dir_in_snapshot[i], path, yaffs_root_dir_path)
279   
280     
281     
282 #########################################copy file into yaffs
283     debug_message("copying scanned files into yaffs", 1)
284     list=[]
285     inode_blacklist=[]
286
287     debug_message("files to be copyied into yaffs", 2)
288     for a in range(0, len(files_in_snapshot)):
289         debug_message(files_in_snapshot[a], 2)
290     debug_message("\n\n\n", 2)
291     for i in range(0, len(files_in_snapshot)):
292         list=[]
293         if files_in_snapshot[i]["num_of_hardlinks"]>1 and files_in_snapshot[i]["inode"] not in inode_blacklist :
294             debug_message("found a hard link", 2)
295             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)
296             for a in range(0, len(files_in_snapshot) ) :
297                 if files_in_snapshot[a]["inode"] ==files_in_snapshot[i]["inode"]  :
298                     ##and os.path.isfile(files_in_snapshot[i])
299                     debug_message(("found this file which matches inode",files_in_snapshot[a]), 2) 
300                     list.append(files_in_snapshot[a])
301                     debug_message(("length of list", len(list)), 2)
302                 if len(list)==files_in_snapshot[i]["num_of_hardlinks"]:
303                     break
304             for a in range(0, len(list)):
305                 debug_message(list[a], 2)
306             ##add inode to blacklist. all of the indoes in the list should be the same.
307             inode_blacklist.append(list[0]["inode"])
308             ##create a file from the first hardlink.
309             create_file(list[0])
310             target_path=yaffs_root_dir_path+list[0]["path"][len(path):]
311             for i in range(1, len(list)):
312                 debug_message("creating_symlink", 2)
313                 debug_message(("target path", target_path), 2)
314                 hardlink_path=yaffs_root_dir_path+list[i]["path"][len(path):]
315                 debug_message(("hardlink path", hardlink_path), 2)
316                 output=yaffs_link(target_path,hardlink_path)
317                 debug_message(("creating hardlink:", list[i]["path"], "output:", output), 1)
318         elif files_in_snapshot[i]["inode"] not in inode_blacklist :
319             create_file(files_in_snapshot[i])
320
321
322 ############################copy symlinks into yaffs
323
324     for i in range(0, len(symlinks_in_snapshot)):
325         debug_message(("symlinks in snapshot:", symlinks_in_snapshot[i]), 2)
326         target_path=join_paths(yaffs_root_dir_path, subtract_paths(symlinks_in_snapshot[i]["target"],  path))
327         new_path=join_paths(yaffs_root_dir_path, subtract_paths(symlinks_in_snapshot[i]["path"], path))
328         output=yaffs_symlink(target_path, new_path)
329         debug_message(("created symlink",new_path , " > ", target_path, "  output:", output), 1)
330         ##yaffs_symlink(const YCHAR *oldpath, const YCHAR *newpath);
331    
332     
333     for i in range(0, len(unknown_in_snapshot)):
334         debug_message( ("unknown object in snapshot:", unknown_in_snapshot[i]), 0)
335     
336     
337 def import_into_yaffs(file_path, yaffs_path="/yaffs2/", debug_level=1,  copy_hidden_dir=True ,new_yaffs_trace_val=0 ):
338 #    global current_debug_level
339 #    global search_hidden_directories
340 #    global yaffs_root_dir_path
341 #    global path
342     
343 #    current_debug_level=debug_level
344 #    search_hidden_directories=copy_hidden_dir
345 #    yaffs_root_dir_path=yaffs_path
346 #    path=file_path
347     old_yaffs_trace_val=yaffs_get_trace()
348     yaffs_set_trace(new_yaffs_trace_val)
349     
350     data=scan_dir(file_path, copy_hidden_dir)
351     copy_scanned_files_into_yaffs(data[0], data[1], data[2], data[3],file_path,  yaffs_path)
352     
353     yaffs_set_trace(old_yaffs_trace_val)
354     
355     
356 if __name__=="__main__":
357     yaffs_StartUp()
358     yaffs_mount("/yaffs2/")
359     yaffs_set_trace(0)
360 #    absolute_path = os.path.abspath(os.path.curdir)
361     #print "absolute path:", absolute_path
362     current_debug_level=1
363     search_hidden_directories=True
364     yaffs_root_dir_path="/yaffs2/scanning/"
365     #print sys.argv
366     path=sys.argv[1]
367     for i in range(2, len(sys.argv)):
368         if sys.argv[i]=="-d":
369             current_debug_level=int( sys.argv[i+1])
370         if sys.argv[i]=="-ignore_hidden_directories":
371             search_hidden_directories=False
372 #
373 #
374 #    path="/home/timothy/work/yaffs/git/yaffs2"
375 #    path="/home/timothy/my_stuff/old_laptop/timothy/programming_lejos/"
376
377
378     import_into_yaffs(path, yaffs_root_dir_path, current_debug_level,  search_hidden_directories, 0 )
379 #    scan_dir(path)
380 #    copy_scanned_files_into_yaffs()
381     #print_scanned_dir_list()
382
383     print"unmounting yaffs:", yaffs_unmount("/yaffs2/")