1 /****************************************************************************
3 * Nintendo Wii/GameCube SMB implementation
6 ****************************************************************************/
13 #include <sys/iosupport.h>
16 #include <ogc/lwp_watchdog.h>
17 #include <ogc/mutex.h>
21 static mutex_t _SMB_mutex
=LWP_MUTEX_NULL
;
23 static inline void _SMB_lock()
25 if(_SMB_mutex
!=LWP_MUTEX_NULL
) LWP_MutexLock(_SMB_mutex
);
28 static inline void _SMB_unlock()
30 if(_SMB_mutex
!=LWP_MUTEX_NULL
) LWP_MutexUnlock(_SMB_mutex
);
38 char filename
[SMB_MAXPATH
];
39 unsigned short access
;
49 static bool FirstInit
=true;
50 #define MAX_SMB_MOUNTED 5
52 ///////////////////////////////////////////
53 // CACHE FUNCTION DEFINITIONS //
54 ///////////////////////////////////////////
55 #define SMB_CACHE_FREE 0xFFFFFFFF
56 #define SMB_READ_BUFFERSIZE 7236
57 #define SMB_WRITE_BUFFERSIZE 7236
75 void DestroySMBReadAheadCache(char *name
);
76 void SMBEnableReadAhead(char *name
, u32 pages
);
77 int ReadSMBFromCache(void *buf
, int len
, SMBFILESTRUCT
*file
);
79 static lwp_t main_thread
;
80 static bool end_cache_thread
= true;
81 ///////////////////////////////////////////
82 // END CACHE FUNCTION DEFINITIONS //
83 ///////////////////////////////////////////
95 char currentpath
[SMB_MAXPATH
];
99 smb_write_cache SMBWriteCache
;
100 smb_cache_page
*SMBReadAheadCache
;
105 static smb_env SMBEnv
[MAX_SMB_MOUNTED
];
108 ///////////////////////////////////////////
109 // CACHE FUNCTIONS //
110 ///////////////////////////////////////////
112 smb_env
* FindSMBEnv(const char *name
)
116 for(i
=0;i
<MAX_SMB_MOUNTED
;i
++)
118 if(SMBEnv
[i
].SMBCONNECTED
&& strcmp(name
,SMBEnv
[i
].name
)==0)
126 int FlushWriteSMBCache(char *name
)
129 env
=FindSMBEnv(name
);
130 if(env
==NULL
) return -1;
132 if (env
->SMBWriteCache
.file
== NULL
|| env
->SMBWriteCache
.len
== 0)
140 written
= SMB_WriteFile(env
->SMBWriteCache
.ptr
, env
->SMBWriteCache
.len
,
141 env
->SMBWriteCache
.file
->offset
, env
->SMBWriteCache
.file
->handle
);
145 env
->SMBWriteCache
.used
= 0;
146 env
->SMBWriteCache
.len
= 0;
147 env
->SMBWriteCache
.file
= NULL
;
151 env
->SMBWriteCache
.file
->offset
+= written
;
152 if (env
->SMBWriteCache
.file
->offset
> env
->SMBWriteCache
.file
->len
)
153 env
->SMBWriteCache
.file
->len
= env
->SMBWriteCache
.file
->offset
;
154 env
->SMBWriteCache
.used
= 0;
155 env
->SMBWriteCache
.len
= 0;
156 env
->SMBWriteCache
.file
= NULL
;
161 void DestroySMBReadAheadCache(char *name
)
164 env
=FindSMBEnv(name
);
165 if(env
==NULL
) return ;
168 if (env
->SMBReadAheadCache
!= NULL
)
170 for (i
= 0; i
< env
->SMB_RA_pages
; i
++)
172 if(env
->SMBReadAheadCache
[i
].ptr
)
173 free(env
->SMBReadAheadCache
[i
].ptr
);
175 free(env
->SMBReadAheadCache
);
176 env
->SMBReadAheadCache
= NULL
;
177 env
->SMB_RA_pages
= 0;
179 //end_cache_thread = true;
181 FlushWriteSMBCache(env
->name
);
183 if(env
->SMBWriteCache
.ptr
)
184 free(env
->SMBWriteCache
.ptr
);
186 env
->SMBWriteCache
.used
= 0;
187 env
->SMBWriteCache
.len
= 0;
188 env
->SMBWriteCache
.file
= NULL
;
189 env
->SMBWriteCache
.ptr
= NULL
;
192 static void *process_cache_thread(void *ptr
)
198 for(i
=0;i
<MAX_SMB_MOUNTED
;i
++)
200 if(SMBEnv
[i
].SMBCONNECTED
)
202 if (SMBEnv
[i
].SMBWriteCache
.used
> 0)
204 if (ticks_to_millisecs(gettime())-ticks_to_millisecs(SMBEnv
[i
].SMBWriteCache
.used
) > 500)
206 FlushWriteSMBCache(SMBEnv
[i
].name
);
213 if (end_cache_thread
) break;
216 LWP_JoinThread(main_thread
, NULL
);
220 void SMBEnableReadAhead(char *name
, u32 pages
)
225 env
=FindSMBEnv(name
);
226 if(env
==NULL
) return;
228 DestroySMBReadAheadCache(name
);
233 //only 1 page for write
234 env
->SMBWriteCache
.ptr
= memalign(32, SMB_WRITE_BUFFERSIZE
);
235 env
->SMBWriteCache
.used
= 0;
236 env
->SMBWriteCache
.len
= 0;
237 env
->SMBWriteCache
.file
= NULL
;
239 env
->SMB_RA_pages
= pages
;
240 env
->SMBReadAheadCache
= (smb_cache_page
*) malloc(sizeof(smb_cache_page
) * env
->SMB_RA_pages
);
241 if (env
->SMBReadAheadCache
== NULL
)
243 for (i
= 0; i
< env
->SMB_RA_pages
; i
++)
245 env
->SMBReadAheadCache
[i
].offset
= SMB_CACHE_FREE
;
246 env
->SMBReadAheadCache
[i
].last_used
= 0;
247 env
->SMBReadAheadCache
[i
].file
= NULL
;
248 env
->SMBReadAheadCache
[i
].ptr
= memalign(32, SMB_READ_BUFFERSIZE
);
249 if (env
->SMBReadAheadCache
[i
].ptr
== NULL
)
251 for (j
= i
- 1; j
>= 0; j
--)
252 if (env
->SMBReadAheadCache
[j
].ptr
)
253 free(env
->SMBReadAheadCache
[j
].ptr
);
254 free(env
->SMBReadAheadCache
);
255 env
->SMBReadAheadCache
= NULL
;
256 free(env
->SMBWriteCache
.ptr
);
259 memset(env
->SMBReadAheadCache
[i
].ptr
, 0, SMB_READ_BUFFERSIZE
);
264 // clear cache from file (clear if you write to the file)
265 void ClearSMBFileCache(SMBFILESTRUCT
*file
)
269 for (i
= 0; i
< SMBEnv
[j
].SMB_RA_pages
; i
++)
271 if (SMBEnv
[j
].SMBReadAheadCache
[i
].offset
!= SMB_CACHE_FREE
)
273 if (strcmp(SMBEnv
[j
].SMBReadAheadCache
[i
].file
->filename
, file
->filename
)==0)
275 SMBEnv
[j
].SMBReadAheadCache
[i
].offset
= SMB_CACHE_FREE
;
276 SMBEnv
[j
].SMBReadAheadCache
[i
].last_used
= 0;
277 SMBEnv
[j
].SMBReadAheadCache
[i
].file
= NULL
;
279 memset(SMBEnv
[j
].SMBReadAheadCache
[i
].ptr
, 0, SMB_READ_BUFFERSIZE
);
285 int ReadSMBFromCache(void *buf
, int len
, SMBFILESTRUCT
*file
)
288 int i
,j
, leastUsed
, rest
;
292 if (SMBEnv
[j
].SMBReadAheadCache
== NULL
)
294 if (SMB_ReadFile(buf
, len
, file
->offset
, file
->handle
) <= 0)
302 new_offset
= file
->offset
;
305 for (i
= 0; i
< SMBEnv
[j
].SMB_RA_pages
; i
++)
307 if (SMBEnv
[j
].SMBReadAheadCache
[i
].file
== file
)
309 if ((file
->offset
>= SMBEnv
[j
].SMBReadAheadCache
[i
].offset
) &&
310 (file
->offset
< (SMBEnv
[j
].SMBReadAheadCache
[i
].offset
+ SMB_READ_BUFFERSIZE
)))
312 if ((file
->offset
+ len
) <= (SMBEnv
[j
].SMBReadAheadCache
[i
].offset
+ SMB_READ_BUFFERSIZE
))
314 SMBEnv
[j
].SMBReadAheadCache
[i
].last_used
= gettime();
315 memcpy(buf
, SMBEnv
[j
].SMBReadAheadCache
[i
].ptr
+ (file
->offset
- SMBEnv
[j
].SMBReadAheadCache
[i
].offset
), len
);
322 SMBEnv
[j
].SMBReadAheadCache
[i
].last_used
= gettime();
323 buffer_used
= (SMBEnv
[j
].SMBReadAheadCache
[i
].offset
+ SMB_READ_BUFFERSIZE
) - file
->offset
;
324 memcpy(buf
, SMBEnv
[j
].SMBReadAheadCache
[i
].ptr
+ (file
->offset
- SMBEnv
[j
].SMBReadAheadCache
[i
].offset
), buffer_used
);
326 rest
= len
- buffer_used
;
327 new_offset
= SMBEnv
[j
].SMBReadAheadCache
[i
].offset
+ SMB_READ_BUFFERSIZE
;
334 if ((SMBEnv
[j
].SMBReadAheadCache
[i
].last_used
< SMBEnv
[j
].SMBReadAheadCache
[leastUsed
].last_used
))
338 for (; i
< SMBEnv
[j
].SMB_RA_pages
; i
++)
340 if ((SMBEnv
[j
].SMBReadAheadCache
[i
].last_used
< SMBEnv
[j
].SMBReadAheadCache
[leastUsed
].last_used
))
344 retval
= SMB_ReadFile(SMBEnv
[j
].SMBReadAheadCache
[leastUsed
].ptr
, SMB_READ_BUFFERSIZE
, new_offset
, file
->handle
);
348 SMBEnv
[j
].SMBReadAheadCache
[leastUsed
].offset
= SMB_CACHE_FREE
;
349 SMBEnv
[j
].SMBReadAheadCache
[leastUsed
].last_used
= 0;
350 SMBEnv
[j
].SMBReadAheadCache
[leastUsed
].file
= NULL
;
355 SMBEnv
[j
].SMBReadAheadCache
[leastUsed
].offset
= new_offset
;
356 SMBEnv
[j
].SMBReadAheadCache
[leastUsed
].last_used
= gettime();
357 SMBEnv
[j
].SMBReadAheadCache
[leastUsed
].file
= file
;
358 memcpy(buf
, SMBEnv
[j
].SMBReadAheadCache
[leastUsed
].ptr
, rest
);
363 int WriteSMBUsingCache(const char *buf
, int len
, SMBFILESTRUCT
*file
)
365 if (file
== NULL
|| buf
== NULL
)
371 if (SMBEnv
[j
].SMBWriteCache
.file
!= NULL
)
373 if (strcmp(SMBEnv
[j
].SMBWriteCache
.file
->filename
, file
->filename
) != 0)
375 //Flush current buffer
376 if (FlushWriteSMBCache(SMBEnv
[j
].name
) < 0)
383 SMBEnv
[j
].SMBWriteCache
.file
= file
;
385 if (SMBEnv
[j
].SMBWriteCache
.len
+ len
>= SMB_WRITE_BUFFERSIZE
)
388 int rest
= 0, written
= 0;
389 send_buf
= memalign(32, SMB_WRITE_BUFFERSIZE
);
390 if (SMBEnv
[j
].SMBWriteCache
.len
> 0)
391 memcpy(send_buf
, SMBEnv
[j
].SMBWriteCache
.ptr
, SMBEnv
[j
].SMBWriteCache
.len
);
393 rest
= SMB_WRITE_BUFFERSIZE
- SMBEnv
[j
].SMBWriteCache
.len
;
394 memcpy(send_buf
+ SMBEnv
[j
].SMBWriteCache
.len
, buf
, rest
);
395 written
= SMB_WriteFile(send_buf
, SMB_WRITE_BUFFERSIZE
,
396 SMBEnv
[j
].SMBWriteCache
.file
->offset
, SMBEnv
[j
].SMBWriteCache
.file
->handle
);
400 SMBEnv
[j
].SMBWriteCache
.used
= 0;
401 SMBEnv
[j
].SMBWriteCache
.len
= 0;
402 SMBEnv
[j
].SMBWriteCache
.file
= NULL
;
406 file
->offset
+= written
;
407 if (file
->offset
> file
->len
)
408 file
->len
= file
->offset
;
411 len
= SMBEnv
[j
].SMBWriteCache
.len
+ len
- SMB_WRITE_BUFFERSIZE
;
413 SMBEnv
[j
].SMBWriteCache
.used
= gettime();
414 SMBEnv
[j
].SMBWriteCache
.len
= 0;
416 if(len
>=SMB_WRITE_BUFFERSIZE
) goto loop
;
420 memcpy(SMBEnv
[j
].SMBWriteCache
.ptr
+ SMBEnv
[j
].SMBWriteCache
.len
, buf
, len
);
421 SMBEnv
[j
].SMBWriteCache
.len
+= len
;
427 ///////////////////////////////////////////
428 // END CACHE FUNCTIONS //
429 ///////////////////////////////////////////
431 static char *smb_absolute_path_no_device(const char *srcpath
, char *destpath
, int env
)
433 if (strchr(srcpath
, ':') != NULL
)
435 srcpath
= strchr(srcpath
, ':') + 1;
437 if (strchr(srcpath
, ':') != NULL
)
442 if (srcpath
[0] != '\\' && srcpath
[0] != '/')
444 strcpy(destpath
, SMBEnv
[env
].currentpath
);
445 strcat(destpath
, srcpath
);
449 strcpy(destpath
, srcpath
);
452 l
= strlen(destpath
);
453 for (i
= 0; i
< l
; i
++)
454 if (destpath
[i
] == '/')
460 char *ExtractDevice(const char *path
, char *device
)
465 for(i
=0;i
<l
&& path
[i
]!='\0' && path
[i
]!=':' && i
< 20;i
++)
467 if(path
[i
]!=':')device
[0]='\0';
473 static int __smb_open(struct _reent
*r
, void *fileStruct
, const char *path
, int flags
, int mode
)
475 SMBFILESTRUCT
*file
= (SMBFILESTRUCT
*) fileStruct
;
478 char fixedpath
[SMB_MAXPATH
];
482 ExtractDevice(path
,fixedpath
);
483 if(fixedpath
[0]=='\0')
485 getcwd(fixedpath
,SMB_MAXPATH
);
486 ExtractDevice(fixedpath
,fixedpath
);
488 env
=FindSMBEnv(fixedpath
);
491 if (!env
->SMBCONNECTED
)
497 if (smb_absolute_path_no_device(path
, fixedpath
, file
->env
) == NULL
)
504 bool fileExists
= true;
506 if (SMB_PathInfo(fixedpath
, &dentry
, env
->smbconn
) != SMB_SUCCESS
)
511 // Determine which mode the file is open for
513 unsigned short access
;
514 if ((flags
& 0x03) == O_RDONLY
)
516 // Open the file for read-only access
517 smb_mode
= SMB_OF_OPEN
;
518 access
= SMB_OPEN_READING
;
520 else if ((flags
& 0x03) == O_WRONLY
)
522 // Open file for write only access
524 smb_mode
= SMB_OF_OPEN
;
526 smb_mode
= SMB_OF_CREATE
;
527 access
= SMB_OPEN_WRITING
;
529 else if ((flags
& 0x03) == O_RDWR
)
531 // Open file for read/write access
532 access
= SMB_OPEN_READWRITE
;
534 smb_mode
= SMB_OF_OPEN
;
536 smb_mode
= SMB_OF_CREATE
;
544 if ((flags
& O_CREAT
) && !fileExists
)
545 smb_mode
= SMB_OF_CREATE
;
546 if (!(flags
& O_APPEND
) && fileExists
&& ((flags
& 0x03) != O_RDONLY
))
547 smb_mode
= SMB_OF_TRUNCATE
;
550 file
->handle
= SMB_OpenFile(fixedpath
, access
, smb_mode
, env
->smbconn
);
560 file
->len
= dentry
.size
;
562 if (flags
& O_APPEND
)
563 file
->offset
= file
->len
;
569 strcpy(file
->filename
, fixedpath
);
573 static off_t
__smb_seek(struct _reent
*r
, int fd
, off_t pos
, int dir
)
575 SMBFILESTRUCT
*file
= (SMBFILESTRUCT
*) fd
;
590 position
= file
->offset
+ pos
;
593 position
= file
->len
+ pos
;
600 if (((pos
> 0) && (position
< 0)) || (position
> file
->len
))
602 r
->_errno
= EOVERFLOW
;
612 file
->offset
= position
;
616 static ssize_t
__smb_read(struct _reent
*r
, int fd
, char *ptr
, size_t len
)
618 SMBFILESTRUCT
*file
= (SMBFILESTRUCT
*) fd
;
626 // Don't try to read if the read pointer is past the end of file
627 if (file
->offset
> file
->len
)
629 r
->_errno
= EOVERFLOW
;
633 // Don't read past end of file
634 if (len
+ file
->offset
> file
->len
)
636 len
= file
->len
- file
->offset
;
639 r
->_errno
= EOVERFLOW
;
645 // Short circuit cases where len is 0 (or less)
648 r
->_errno
= EOVERFLOW
;
654 if (ReadSMBFromCache(ptr
, len
, file
) < 0)
661 if(CheckSMBConnection(SMBEnv
[file
->env
].name
))
663 ClearSMBFileCache(file
);
664 file
->handle
= SMB_OpenFile(file
->filename
, file
->access
, SMB_OF_OPEN
, SMBEnv
[file
->env
].smbconn
);
676 goto retry_reconnect
;
678 r
->_errno
= EOVERFLOW
;
687 static ssize_t
__smb_write(struct _reent
*r
, int fd
, const char *ptr
, size_t len
)
689 SMBFILESTRUCT
*file
= (SMBFILESTRUCT
*) fd
;
697 // Don't try to write if the pointer is past the end of file
698 if (file
->offset
> file
->len
)
700 r
->_errno
= EOVERFLOW
;
704 // Short circuit cases where len is 0 (or less)
707 r
->_errno
= EOVERFLOW
;
711 ClearSMBFileCache(file
);
712 written
= WriteSMBUsingCache(ptr
, len
, file
);
722 static int __smb_close(struct _reent
*r
, int fd
)
724 SMBFILESTRUCT
*file
= (SMBFILESTRUCT
*) fd
;
728 if (SMBEnv
[j
].SMBWriteCache
.file
== file
)
730 FlushWriteSMBCache(SMBEnv
[j
].name
);
732 ClearSMBFileCache(file
);
733 SMB_CloseFile(file
->handle
);
737 file
->filename
[0] = '\0';
742 static int __smb_chdir(struct _reent
*r
, const char *path
)
744 char path_absolute
[SMB_MAXPATH
];
749 ExtractDevice(path
,path_absolute
);
750 if(path_absolute
[0]=='\0')
752 getcwd(path_absolute
,SMB_MAXPATH
);
753 ExtractDevice(path_absolute
,path_absolute
);
757 env
=FindSMBEnv(path_absolute
);
759 if (smb_absolute_path_no_device(path
, path_absolute
,env
->pos
) == NULL
)
765 memset(&dentry
, 0, sizeof(SMBDIRENTRY
));
768 found
= SMB_PathInfo(path_absolute
, &dentry
, env
->smbconn
);
771 if (found
!= SMB_SUCCESS
)
777 if (!(dentry
.attributes
& SMB_SRCH_DIRECTORY
))
783 strcpy(env
->currentpath
, path_absolute
);
784 if (env
->currentpath
[0] != 0)
786 if (env
->currentpath
[strlen(env
->currentpath
) - 1] != '\\')
787 strcat(env
->currentpath
, "\\");
793 static int __smb_dirreset(struct _reent
*r
, DIR_ITER
*dirState
)
795 char path_abs
[SMB_MAXPATH
];
796 SMBDIRSTATESTRUCT
* state
= (SMBDIRSTATESTRUCT
*) (dirState
->dirStruct
);
799 memset(&dentry
, 0, sizeof(SMBDIRENTRY
));
802 SMB_FindClose(SMBEnv
[state
->env
].smbconn
);
804 strcpy(path_abs
,SMBEnv
[state
->env
].currentpath
);
805 strcat(path_abs
,"*");
806 int found
= SMB_FindFirst(path_abs
, SMB_SRCH_DIRECTORY
| SMB_SRCH_SYSTEM
| SMB_SRCH_HIDDEN
| SMB_SRCH_READONLY
| SMB_SRCH_ARCHIVE
, &dentry
, SMBEnv
[state
->env
].smbconn
);
809 if (found
!= SMB_SUCCESS
)
815 if (!(dentry
.attributes
& SMB_SRCH_DIRECTORY
))
821 state
->smbdir
.size
= dentry
.size
;
822 state
->smbdir
.ctime
= dentry
.ctime
;
823 state
->smbdir
.atime
= dentry
.atime
;
824 state
->smbdir
.mtime
= dentry
.mtime
;
825 state
->smbdir
.attributes
= dentry
.attributes
;
826 strcpy(state
->smbdir
.name
, dentry
.name
);
828 SMBEnv
[state
->env
].first_item_dir
= true;
832 static DIR_ITER
* __smb_diropen(struct _reent
*r
, DIR_ITER
*dirState
, const char *path
)
834 char path_absolute
[SMB_MAXPATH
];
836 SMBDIRSTATESTRUCT
* state
= (SMBDIRSTATESTRUCT
*) (dirState
->dirStruct
);
839 ExtractDevice(path
,path_absolute
);
840 if(path_absolute
[0]=='\0')
842 getcwd(path_absolute
,SMB_MAXPATH
);
843 ExtractDevice(path_absolute
,path_absolute
);
847 env
=FindSMBEnv(path_absolute
);
848 if (smb_absolute_path_no_device(path
, path_absolute
, env
->pos
) == NULL
)
853 if (path_absolute
[strlen(path_absolute
) - 1] != '\\')
854 strcat(path_absolute
, "\\");
856 if(!strcmp(path_absolute
,"\\"))
857 env
->diropen_root
=true;
859 env
->diropen_root
=false;
861 strcat(path_absolute
, "*");
864 memset(&dentry
, 0, sizeof(SMBDIRENTRY
));
866 found
= SMB_FindFirst(path_absolute
, SMB_SRCH_DIRECTORY
| SMB_SRCH_SYSTEM
| SMB_SRCH_HIDDEN
| SMB_SRCH_READONLY
| SMB_SRCH_ARCHIVE
, &dentry
, env
->smbconn
);
869 if (found
!= SMB_SUCCESS
)
875 if (!(dentry
.attributes
& SMB_SRCH_DIRECTORY
))
882 state
->smbdir
.size
= dentry
.size
;
883 state
->smbdir
.ctime
= dentry
.ctime
;
884 state
->smbdir
.atime
= dentry
.atime
;
885 state
->smbdir
.mtime
= dentry
.mtime
;
886 state
->smbdir
.attributes
= dentry
.attributes
;
887 strcpy(state
->smbdir
.name
, dentry
.name
);
888 env
->first_item_dir
= true;
892 static int dentry_to_stat(SMBDIRENTRY
*dentry
, struct stat
*st
)
902 st
->st_mode
= ((dentry
->attributes
& SMB_SRCH_DIRECTORY
) ? S_IFDIR
905 st
->st_uid
= 1; // Faked
906 st
->st_rdev
= st
->st_dev
;
907 st
->st_gid
= 2; // Faked
908 st
->st_size
= dentry
->size
;
909 st
->st_atime
= dentry
->atime
/10000000.0 - 11644473600LL;
911 st
->st_mtime
= dentry
->mtime
/10000000.0 - 11644473600LL;
913 st
->st_ctime
= dentry
->ctime
/10000000.0 - 11644473600LL;
915 st
->st_blksize
= 1024;
916 st
->st_blocks
= (st
->st_size
+ st
->st_blksize
- 1) / st
->st_blksize
; // File size in blocks
917 st
->st_spare4
[0] = 0;
918 st
->st_spare4
[1] = 0;
923 static int __smb_dirnext(struct _reent
*r
, DIR_ITER
*dirState
, char *filename
,
924 struct stat
*filestat
)
927 SMBDIRSTATESTRUCT
* state
= (SMBDIRSTATESTRUCT
*) (dirState
->dirStruct
);
930 if (SMBEnv
[state
->env
].currentpath
[0] == '\0' || filestat
== NULL
)
936 memset(&dentry
, 0, sizeof(SMBDIRENTRY
));
937 if (SMBEnv
[state
->env
].first_item_dir
)
939 SMBEnv
[state
->env
].first_item_dir
= false;
941 dentry
.attributes
= SMB_SRCH_DIRECTORY
;
942 strcpy(dentry
.name
, ".");
944 state
->smbdir
.size
= dentry
.size
;
945 state
->smbdir
.ctime
= dentry
.ctime
;
946 state
->smbdir
.atime
= dentry
.atime
;
947 state
->smbdir
.mtime
= dentry
.mtime
;
948 state
->smbdir
.attributes
= dentry
.attributes
;
949 strcpy(state
->smbdir
.name
, dentry
.name
);
950 strcpy(filename
, dentry
.name
);
951 dentry_to_stat(&dentry
, filestat
);
957 ret
= SMB_FindNext(&dentry
, SMBEnv
[state
->env
].smbconn
);
958 if(ret
==SMB_SUCCESS
&& SMBEnv
[state
->env
].diropen_root
&& !strcmp(dentry
.name
,".."))
959 ret
= SMB_FindNext(&dentry
, SMBEnv
[state
->env
].smbconn
);
962 if (ret
== SMB_SUCCESS
)
964 state
->smbdir
.size
= dentry
.size
;
965 state
->smbdir
.ctime
= dentry
.ctime
;
966 state
->smbdir
.atime
= dentry
.atime
;
967 state
->smbdir
.mtime
= dentry
.mtime
;
968 state
->smbdir
.attributes
= dentry
.attributes
;
969 strcpy(state
->smbdir
.name
, dentry
.name
);
977 strcpy(filename
, dentry
.name
);
979 dentry_to_stat(&dentry
, filestat
);
984 static int __smb_dirclose(struct _reent
*r
, DIR_ITER
*dirState
)
986 SMBDIRSTATESTRUCT
* state
= (SMBDIRSTATESTRUCT
*) (dirState
->dirStruct
);
989 SMB_FindClose(SMBEnv
[state
->env
].smbconn
);
992 memset(state
, 0, sizeof(SMBDIRSTATESTRUCT
));
996 static int __smb_stat(struct _reent
*r
, const char *path
, struct stat
*st
)
998 char path_absolute
[SMB_MAXPATH
];
1001 ExtractDevice(path
,path_absolute
);
1002 if(path_absolute
[0]=='\0')
1004 getcwd(path_absolute
,SMB_MAXPATH
);
1005 ExtractDevice(path_absolute
,path_absolute
);
1009 env
=FindSMBEnv(path_absolute
);
1011 if (smb_absolute_path_no_device(path
, path_absolute
, env
->pos
) == NULL
)
1017 if (SMB_PathInfo(path_absolute
, &dentry
, env
->smbconn
) != SMB_SUCCESS
)
1025 if (dentry
.name
[0] == '\0')
1031 dentry_to_stat(&dentry
, st
);
1036 static int __smb_fstat(struct _reent
*r
, int fd
, struct stat
*st
)
1038 SMBFILESTRUCT
*filestate
= (SMBFILESTRUCT
*) fd
;
1046 st
->st_size
= filestate
->len
;
1051 void MountDevice(const char *name
,SMBCONN smbconn
, int env
)
1053 devoptab_t
*dotab_smb
;
1055 dotab_smb
=(devoptab_t
*)malloc(sizeof(devoptab_t
));
1057 dotab_smb
->name
=strdup(name
);
1058 dotab_smb
->structSize
=sizeof(SMBFILESTRUCT
); // size of file structure
1059 dotab_smb
->open_r
=__smb_open
; // device open
1060 dotab_smb
->close_r
=__smb_close
; // device close
1061 dotab_smb
->write_r
=__smb_write
; // device write
1062 dotab_smb
->read_r
=__smb_read
; // device read
1063 dotab_smb
->seek_r
=__smb_seek
; // device seek
1064 dotab_smb
->fstat_r
=__smb_fstat
; // device fstat
1065 dotab_smb
->stat_r
=__smb_stat
; // device stat
1066 dotab_smb
->link_r
=NULL
; // device link
1067 dotab_smb
->unlink_r
=NULL
; // device unlink
1068 dotab_smb
->chdir_r
=__smb_chdir
; // device chdir
1069 dotab_smb
->rename_r
=NULL
; // device rename
1070 dotab_smb
->mkdir_r
=NULL
; // device mkdir
1072 dotab_smb
->dirStateSize
=sizeof(SMBDIRSTATESTRUCT
); // dirStateSize
1073 dotab_smb
->diropen_r
=__smb_diropen
; // device diropen_r
1074 dotab_smb
->dirreset_r
=__smb_dirreset
; // device dirreset_r
1075 dotab_smb
->dirnext_r
=__smb_dirnext
; // device dirnext_r
1076 dotab_smb
->dirclose_r
=__smb_dirclose
; // device dirclose_r
1077 dotab_smb
->statvfs_r
=NULL
; // device statvfs_r
1078 dotab_smb
->ftruncate_r
=NULL
; // device ftruncate_r
1079 dotab_smb
->fsync_r
=NULL
; // device fsync_r
1080 dotab_smb
->deviceData
=NULL
; /* Device data */
1082 AddDevice(dotab_smb
);
1084 SMBEnv
[env
].pos
=env
;
1085 SMBEnv
[env
].smbconn
=smbconn
;
1086 SMBEnv
[env
].name
=strdup(name
);
1087 SMBEnv
[env
].SMBCONNECTED
=true;
1088 SMBEnv
[env
].first_item_dir
=false;
1089 SMBEnv
[env
].diropen_root
=false;
1090 SMBEnv
[env
].devoptab
=dotab_smb
;
1092 SMBEnableReadAhead(SMBEnv
[env
].name
,32);
1095 bool smbInitDevice(const char* name
, const char *user
, const char *password
, const char *share
, const char *ip
)
1101 for(i
=0;i
<MAX_SMB_MOUNTED
;i
++)
1103 SMBEnv
[i
].SMBCONNECTED
=false;
1104 SMBEnv
[i
].currentpath
[0]='\\';
1105 SMBEnv
[i
].currentpath
[1]='\0';
1106 SMBEnv
[i
].first_item_dir
=false;
1108 SMBEnv
[i
].SMBReadAheadCache
=NULL
;
1113 for(i
=0;i
<MAX_SMB_MOUNTED
&& SMBEnv
[i
].SMBCONNECTED
;i
++);
1114 if(i
==MAX_SMB_MOUNTED
) return false; //all allowed samba connections reached
1116 if (if_config(myIP
, NULL
, NULL
, true) < 0)
1119 if(_SMB_mutex
==LWP_MUTEX_NULL
)LWP_MutexInit(&_SMB_mutex
, false);
1123 if (SMB_Connect(&smbconn
, user
, password
, share
, ip
) != SMB_SUCCESS
)
1126 //LWP_MutexDestroy(_SMB_mutex);
1131 MountDevice(name
,smbconn
,i
);
1133 if(end_cache_thread
== true) // never close thread
1135 lwp_t client_thread
;
1136 main_thread
= LWP_GetSelf();
1137 end_cache_thread
= false;
1138 LWP_CreateThread(&client_thread
, process_cache_thread
, NULL
, NULL
, 0, 80);
1143 bool smbInit(const char *user
, const char *password
, const char *share
, const char *ip
)
1145 return smbInitDevice("smb", user
, password
, share
, ip
);
1148 void smbClose(const char* name
)
1151 env
=FindSMBEnv(name
);
1152 if(env
==NULL
) return;
1154 if(env
->SMBCONNECTED
)
1157 SMB_Close(env
->smbconn
);
1160 env
->SMBCONNECTED
=false;
1161 RemoveDevice(env
->name
);
1162 //LWP_MutexDestroy(_SMB_mutex);
1165 bool CheckSMBConnection(const char* name
)
1172 for(i
=0;i
<50 && name
[i
]!='\0' && name
[i
]!=':';i
++) device
[i
]=name
[i
];
1175 env
=FindSMBEnv(device
);
1176 if(env
==NULL
) return false;
1178 ret
=(SMB_Reconnect(&env
->smbconn
,true)==SMB_SUCCESS
);