📄 file.c
字号:
rc = CIFSFindFirst(xid, pTcon, full_path, pfindData, &findParms, cifs_sb->local_nls, &Unicode, &UnixSearch); cFYI(1, ("Count: %d End: %d ", le16_to_cpu(findParms.SearchCount), le16_to_cpu(findParms.EndofSearch))); if (rc == 0) { __u16 count = le16_to_cpu(findParms.SearchCount); searchHandle = findParms.SearchHandle; if(file->private_data == NULL) file->private_data = kmalloc(sizeof(struct cifsFileInfo),GFP_KERNEL); if (file->private_data) { memset(file->private_data, 0, sizeof (struct cifsFileInfo)); cifsFile = (struct cifsFileInfo *) file->private_data; cifsFile->netfid = searchHandle; cifsFile->invalidHandle = FALSE; init_MUTEX(&cifsFile->fh_sem); } else { rc = -ENOMEM; break; } renew_parental_timestamps(file->f_dentry); lastFindData = (FILE_DIRECTORY_INFO *) ((char *) pfindData + le16_to_cpu(findParms.LastNameOffset)); if((char *)lastFindData > (char *)pfindData + bufsize) { cFYI(1,("last search entry past end of packet")); rc = -EIO; break; } /* Offset of resume key same for levels 257 and 514 */ cifsFile->resume_key = lastFindData->FileIndex; if(UnixSearch == FALSE) { cifsFile->resume_name_length = le32_to_cpu(lastFindData->FileNameLength); if(cifsFile->resume_name_length > bufsize - 64) { cFYI(1,("Illegal resume file name length %d", cifsFile->resume_name_length)); rc = -ENOMEM; break; } cifsFile->search_resume_name = kmalloc(cifsFile->resume_name_length, GFP_KERNEL); cFYI(1,("Last file: %s with name %d bytes long", lastFindData->FileName, cifsFile->resume_name_length)); if(cifsFile->search_resume_name == NULL) { rc = -ENOMEM; break; } memcpy(cifsFile->search_resume_name, lastFindData->FileName, cifsFile->resume_name_length); } else { pfindDataUnix = (FILE_UNIX_INFO *)lastFindData; if (Unicode == TRUE) { for(i=0;(pfindDataUnix->FileName[i] | pfindDataUnix->FileName[i+1]); i+=2) { if(i > bufsize-64) break; } cifsFile->resume_name_length = i + 2; } else { cifsFile->resume_name_length = strnlen(pfindDataUnix->FileName, bufsize-63); } if(cifsFile->resume_name_length > bufsize - 64) { cFYI(1,("Illegal resume file name length %d", cifsFile->resume_name_length)); rc = -ENOMEM; break; } cifsFile->search_resume_name = kmalloc(cifsFile->resume_name_length, GFP_KERNEL); cFYI(1,("Last file: %s with name %d bytes long", pfindDataUnix->FileName, cifsFile->resume_name_length)); if(cifsFile->search_resume_name == NULL) { rc = -ENOMEM; break; } memcpy(cifsFile->search_resume_name, pfindDataUnix->FileName, cifsFile->resume_name_length); } for (i = 2; i < count + 2; i++) { if (UnixSearch == FALSE) { __u32 len = le32_to_cpu(pfindData->FileNameLength); if (Unicode == TRUE) len = cifs_strfromUCS_le (pfindData->FileName, (wchar_t *) pfindData->FileName, len / 2, cifs_sb->local_nls); qstring.len = len; if (((len != 1) || (pfindData->FileName[0] != '.')) && ((len != 2) || (pfindData-> FileName[0] != '.') || (pfindData-> FileName[1] != '.'))) { if(cifs_filldir(&qstring, pfindData, file, filldir, direntry)) { /* do not end search if kernel not ready to take remaining entries yet */ reset_resume_key(file, pfindData->FileName,qstring.len, Unicode, cifs_sb->local_nls); findParms.EndofSearch = 0; break; } file->f_pos++; } } else { /* UnixSearch */ pfindDataUnix = (FILE_UNIX_INFO *) pfindData; if (Unicode == TRUE) qstring.len = cifs_strfromUCS_le (pfindDataUnix->FileName, (wchar_t *) pfindDataUnix->FileName, MAX_PATHCONF, cifs_sb->local_nls); else qstring.len = strnlen(pfindDataUnix-> FileName, MAX_PATHCONF); if (((qstring.len != 1) || (pfindDataUnix-> FileName[0] != '.')) && ((qstring.len != 2) || (pfindDataUnix-> FileName[0] != '.') || (pfindDataUnix-> FileName[1] != '.'))) { if(cifs_filldir_unix(&qstring, pfindDataUnix, file, filldir, direntry)) { /* do not end search if kernel not ready to take remaining entries yet */ findParms.EndofSearch = 0; reset_resume_key(file, pfindDataUnix->FileName, qstring.len,Unicode,cifs_sb->local_nls); break; } file->f_pos++; } } /* works also for Unix ff struct since first field of both */ pfindData = (FILE_DIRECTORY_INFO *) ((char *) pfindData + le32_to_cpu(pfindData->NextEntryOffset)); /* BB also should check to make sure that pointer is not beyond the end of the SMB */ /* if(pfindData > lastFindData) rc = -EIO; break; */ } /* end for loop */ if ((findParms.EndofSearch != 0) && cifsFile) { cifsFile->endOfSearch = TRUE; if(findParms.SearchCount == cpu_to_le16(2)) cifsFile->emptyDir = TRUE; } } else { if (cifsFile) cifsFile->endOfSearch = TRUE; /* unless parent directory gone do not return error */ rc = 0; } break; default: if (file->private_data == NULL) { rc = -EBADF; cFYI(1, ("Readdir on closed srch, pos = %lld", file->f_pos)); } else { cifsFile = (struct cifsFileInfo *) file->private_data; if (cifsFile->endOfSearch) { rc = 0; cFYI(1, ("End of search ")); break; } searchHandle = cifsFile->netfid; rc = CIFSFindNext(xid, pTcon, pfindData, &findNextParms, searchHandle, cifsFile->search_resume_name, cifsFile->resume_name_length, cifsFile->resume_key, &Unicode, &UnixSearch); cFYI(1,("Count: %d End: %d ", le16_to_cpu(findNextParms.SearchCount), le16_to_cpu(findNextParms.EndofSearch))); if ((rc == 0) && (findNextParms.SearchCount != 0)) { /* BB save off resume key, key name and name length */ __u16 count = le16_to_cpu(findNextParms.SearchCount); lastFindData = (FILE_DIRECTORY_INFO *) ((char *) pfindData + le16_to_cpu(findNextParms.LastNameOffset)); if((char *)lastFindData > (char *)pfindData + bufsize) { cFYI(1,("last search entry past end of packet")); rc = -EIO; break; } /* Offset of resume key same for levels 257 and 514 */ cifsFile->resume_key = lastFindData->FileIndex; if(UnixSearch == FALSE) { cifsFile->resume_name_length = le32_to_cpu(lastFindData->FileNameLength); if(cifsFile->resume_name_length > bufsize - 64) { cFYI(1,("Illegal resume file name length %d", cifsFile->resume_name_length)); rc = -ENOMEM; break; } /* Free the memory allocated by previous findfirst or findnext call - we can not reuse the memory since the resume name may not be same string length */ if(cifsFile->search_resume_name) kfree(cifsFile->search_resume_name); cifsFile->search_resume_name = kmalloc(cifsFile->resume_name_length, GFP_KERNEL); cFYI(1,("Last file: %s with name %d bytes long", lastFindData->FileName, cifsFile->resume_name_length)); if(cifsFile->search_resume_name == NULL) { rc = -ENOMEM; break; } memcpy(cifsFile->search_resume_name, lastFindData->FileName, cifsFile->resume_name_length); } else { pfindDataUnix = (FILE_UNIX_INFO *)lastFindData; if (Unicode == TRUE) { for(i=0;(pfindDataUnix->FileName[i] | pfindDataUnix->FileName[i+1]); i+=2) { if(i > bufsize-64) break; } cifsFile->resume_name_length = i + 2; } else { cifsFile->resume_name_length = strnlen(pfindDataUnix-> FileName, MAX_PATHCONF); } if(cifsFile->resume_name_length > bufsize - 64) { cFYI(1,("Illegal resume file name length %d", cifsFile->resume_name_length)); rc = -ENOMEM; break; } /* Free the memory allocated by previous findfirst or findnext call - we can not reuse the memory since the resume name may not be same string length */ if(cifsFile->search_resume_name) kfree(cifsFile->search_resume_name); cifsFile->search_resume_name = kmalloc(cifsFile->resume_name_length, GFP_KERNEL); cFYI(1,("fnext last file: %s with name %d bytes long", pfindDataUnix->FileName, cifsFile->resume_name_length)); if(cifsFile->search_resume_name == NULL) { rc = -ENOMEM; break; } memcpy(cifsFile->search_resume_name, pfindDataUnix->FileName, cifsFile->resume_name_length); } for (i = 0; i < count; i++) { __u32 len = le32_to_cpu(pfindData-> FileNameLength); if (UnixSearch == FALSE) { if (Unicode == TRUE) len = cifs_strfromUCS_le (pfindData->FileName, (wchar_t *) pfindData->FileName, len / 2, cifs_sb->local_nls); qstring.len = len; if (((len != 1) || (pfindData->FileName[0] != '.')) && ((len != 2) || (pfindData->FileName[0] != '.') || (pfindData->FileName[1] != '.'))) { if(cifs_filldir (&qstring, pfindData, file, filldir, direntry)) { /* do not end search if kernel not ready to take remaining entries yet */ findNextParms.EndofSearch = 0; reset_resume_key(file, pfindData->FileName,qstring.len, Unicode,cifs_sb->local_nls); break; } file->f_pos++; } } else { /* UnixSearch */ pfindDataUnix = (FILE_UNIX_INFO *) pfindData; if (Unicode == TRUE) qstring.len = cifs_strfromUCS_le (pfindDataUnix->FileName, (wchar_t *) pfindDataUnix->FileName, MAX_PATHCONF, cifs_sb->local_nls); else qstring.len = strnlen (pfindDataUnix-> FileName, MAX_PATHCONF); if (((qstring.len != 1) || (pfindDataUnix-> FileName[0] != '.')) && ((qstring.len != 2) || (pfindDataUnix-> FileName[0] != '.') || (pfindDataUnix-> FileName[1] != '.'))) { if(cifs_filldir_unix (&qstring, pfindDataUnix, file, filldir, direntry)) { /* do not end search if kernel not ready to take remaining entries yet */ findNextParms.EndofSearch = 0; reset_resume_key(file, pfindDataUnix->FileName,qstring.len, Unicode,cifs_sb->local_nls); break; } file->f_pos++; } } pfindData = (FILE_DIRECTORY_INFO *) ((char *) pfindData + le32_to_cpu(pfindData->NextEntryOffset)); /* works also for Unix find struct since first field of both */ /* BB also should check to ensure pointer not beyond end of SMB */ } /* end for loop */ if (findNextParms.EndofSearch != 0) { cifsFile->endOfSearch = TRUE; } } else { cifsFile->endOfSearch = TRUE; rc = 0; /* unless parent directory disappeared - do not return error here (eg Access Denied or no more files) */ } } } /* end switch */ if (data) kfree(data); if (full_path) kfree(full_path); FreeXid(xid); return rc;}int cifs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to){ int rc = 0; loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT; cFYI(1,("prepare write for page %p from %d to %d",page,from,to)); if (!PageUptodate(page)) { /* if (to - from != PAGE_CACHE_SIZE) { void *kaddr = kmap_atomic(page, KM_USER0); memset(kaddr, 0, from); memset(kaddr + to, 0, PAGE_CACHE_SIZE - to); flush_dcache_page(page); kunmap_atomic(kaddr, KM_USER0); } */ /* If we are writing a full page it will be up to date, no need to read from the server */ if((to==PAGE_CACHE_SIZE) && (from == 0)) SetPageUptodate(page); /* might as well read a page, it is fast enough */ if((file->f_flags & O_ACCMODE) != O_WRONLY) { rc = cifs_readpage_worker(file,page,&offset); } else { /* should we try using another file handle if there is one - how would we lock it to prevent close of that handle racing with this read? */ /* In any case this will be written out by commit_write */ } } /* BB should we pass any errors back? e.g. if we do not have read access to the file */ return 0;}struct address_space_operations cifs_addr_ops = { .readpage = cifs_readpage, .readpages = cifs_readpages, .writepage = cifs_writepage, .prepare_write = cifs_prepare_write, .commit_write = cifs_commit_write, .set_page_dirty = __set_page_dirty_nobuffers, /* .sync_page = cifs_sync_page, */ /*.direct_IO = */};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -