vendor/github.com/spf13/afero/memmap.go
changeset 256 6d9efbef00a9
parent 242 2a9ec03fe5a1
child 260 445e01aede7e
equal deleted inserted replaced
255:4f153a23adab 256:6d9efbef00a9
    23 	"time"
    23 	"time"
    24 
    24 
    25 	"github.com/spf13/afero/mem"
    25 	"github.com/spf13/afero/mem"
    26 )
    26 )
    27 
    27 
       
    28 const chmodBits = os.ModePerm | os.ModeSetuid | os.ModeSetgid | os.ModeSticky // Only a subset of bits are allowed to be changed. Documented under os.Chmod()
       
    29 
    28 type MemMapFs struct {
    30 type MemMapFs struct {
    29 	mu   sync.RWMutex
    31 	mu   sync.RWMutex
    30 	data map[string]*mem.FileData
    32 	data map[string]*mem.FileData
    31 	init sync.Once
    33 	init sync.Once
    32 }
    34 }
    38 func (m *MemMapFs) getData() map[string]*mem.FileData {
    40 func (m *MemMapFs) getData() map[string]*mem.FileData {
    39 	m.init.Do(func() {
    41 	m.init.Do(func() {
    40 		m.data = make(map[string]*mem.FileData)
    42 		m.data = make(map[string]*mem.FileData)
    41 		// Root should always exist, right?
    43 		// Root should always exist, right?
    42 		// TODO: what about windows?
    44 		// TODO: what about windows?
    43 		m.data[FilePathSeparator] = mem.CreateDir(FilePathSeparator)
    45 		root := mem.CreateDir(FilePathSeparator)
       
    46 		mem.SetMode(root, os.ModeDir|0755)
       
    47 		m.data[FilePathSeparator] = root
    44 	})
    48 	})
    45 	return m.data
    49 	return m.data
    46 }
    50 }
    47 
    51 
    48 func (*MemMapFs) Name() string { return "MemMapFS" }
    52 func (*MemMapFs) Name() string { return "MemMapFS" }
    50 func (m *MemMapFs) Create(name string) (File, error) {
    54 func (m *MemMapFs) Create(name string) (File, error) {
    51 	name = normalizePath(name)
    55 	name = normalizePath(name)
    52 	m.mu.Lock()
    56 	m.mu.Lock()
    53 	file := mem.CreateFile(name)
    57 	file := mem.CreateFile(name)
    54 	m.getData()[name] = file
    58 	m.getData()[name] = file
    55 	m.registerWithParent(file)
    59 	m.registerWithParent(file, 0)
    56 	m.mu.Unlock()
    60 	m.mu.Unlock()
    57 	return mem.NewFileHandle(file), nil
    61 	return mem.NewFileHandle(file), nil
    58 }
    62 }
    59 
    63 
    60 func (m *MemMapFs) unRegisterWithParent(fileName string) error {
    64 func (m *MemMapFs) unRegisterWithParent(fileName string) error {
    81 		return nil
    85 		return nil
    82 	}
    86 	}
    83 	return pfile
    87 	return pfile
    84 }
    88 }
    85 
    89 
    86 func (m *MemMapFs) registerWithParent(f *mem.FileData) {
    90 func (m *MemMapFs) registerWithParent(f *mem.FileData, perm os.FileMode) {
    87 	if f == nil {
    91 	if f == nil {
    88 		return
    92 		return
    89 	}
    93 	}
    90 	parent := m.findParent(f)
    94 	parent := m.findParent(f)
    91 	if parent == nil {
    95 	if parent == nil {
    92 		pdir := filepath.Dir(filepath.Clean(f.Name()))
    96 		pdir := filepath.Dir(filepath.Clean(f.Name()))
    93 		err := m.lockfreeMkdir(pdir, 0777)
    97 		err := m.lockfreeMkdir(pdir, perm)
    94 		if err != nil {
    98 		if err != nil {
    95 			//log.Println("Mkdir error:", err)
    99 			//log.Println("Mkdir error:", err)
    96 			return
   100 			return
    97 		}
   101 		}
    98 		parent, err = m.lockfreeOpen(pdir)
   102 		parent, err = m.lockfreeOpen(pdir)
   117 		if !i.IsDir() {
   121 		if !i.IsDir() {
   118 			return ErrFileExists
   122 			return ErrFileExists
   119 		}
   123 		}
   120 	} else {
   124 	} else {
   121 		item := mem.CreateDir(name)
   125 		item := mem.CreateDir(name)
       
   126 		mem.SetMode(item, os.ModeDir|perm)
   122 		m.getData()[name] = item
   127 		m.getData()[name] = item
   123 		m.registerWithParent(item)
   128 		m.registerWithParent(item, perm)
   124 	}
   129 	}
   125 	return nil
   130 	return nil
   126 }
   131 }
   127 
   132 
   128 func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error {
   133 func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error {
       
   134 	perm &= chmodBits
   129 	name = normalizePath(name)
   135 	name = normalizePath(name)
   130 
   136 
   131 	m.mu.RLock()
   137 	m.mu.RLock()
   132 	_, ok := m.getData()[name]
   138 	_, ok := m.getData()[name]
   133 	m.mu.RUnlock()
   139 	m.mu.RUnlock()
   135 		return &os.PathError{Op: "mkdir", Path: name, Err: ErrFileExists}
   141 		return &os.PathError{Op: "mkdir", Path: name, Err: ErrFileExists}
   136 	}
   142 	}
   137 
   143 
   138 	m.mu.Lock()
   144 	m.mu.Lock()
   139 	item := mem.CreateDir(name)
   145 	item := mem.CreateDir(name)
       
   146 	mem.SetMode(item, os.ModeDir|perm)
   140 	m.getData()[name] = item
   147 	m.getData()[name] = item
   141 	m.registerWithParent(item)
   148 	m.registerWithParent(item, perm)
   142 	m.mu.Unlock()
   149 	m.mu.Unlock()
   143 
   150 
   144 	m.Chmod(name, perm|os.ModeDir)
   151 	return m.setFileMode(name, perm|os.ModeDir)
   145 
       
   146 	return nil
       
   147 }
   152 }
   148 
   153 
   149 func (m *MemMapFs) MkdirAll(path string, perm os.FileMode) error {
   154 func (m *MemMapFs) MkdirAll(path string, perm os.FileMode) error {
   150 	err := m.Mkdir(path, perm)
   155 	err := m.Mkdir(path, perm)
   151 	if err != nil {
   156 	if err != nil {
   208 		return nil, ErrFileNotFound
   213 		return nil, ErrFileNotFound
   209 	}
   214 	}
   210 }
   215 }
   211 
   216 
   212 func (m *MemMapFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
   217 func (m *MemMapFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
       
   218 	perm &= chmodBits
   213 	chmod := false
   219 	chmod := false
   214 	file, err := m.openWrite(name)
   220 	file, err := m.openWrite(name)
       
   221 	if err == nil && (flag&os.O_EXCL > 0) {
       
   222 		return nil, &os.PathError{Op: "open", Path: name, Err: ErrFileExists}
       
   223 	}
   215 	if os.IsNotExist(err) && (flag&os.O_CREATE > 0) {
   224 	if os.IsNotExist(err) && (flag&os.O_CREATE > 0) {
   216 		file, err = m.Create(name)
   225 		file, err = m.Create(name)
   217 		chmod = true
   226 		chmod = true
   218 	}
   227 	}
   219 	if err != nil {
   228 	if err != nil {
   235 			file.Close()
   244 			file.Close()
   236 			return nil, err
   245 			return nil, err
   237 		}
   246 		}
   238 	}
   247 	}
   239 	if chmod {
   248 	if chmod {
   240 		m.Chmod(name, perm)
   249 		return file, m.setFileMode(name, perm)
   241 	}
   250 	}
   242 	return file, nil
   251 	return file, nil
   243 }
   252 }
   244 
   253 
   245 func (m *MemMapFs) Remove(name string) error {
   254 func (m *MemMapFs) Remove(name string) error {
   267 	m.mu.Unlock()
   276 	m.mu.Unlock()
   268 
   277 
   269 	m.mu.RLock()
   278 	m.mu.RLock()
   270 	defer m.mu.RUnlock()
   279 	defer m.mu.RUnlock()
   271 
   280 
   272 	for p, _ := range m.getData() {
   281 	for p := range m.getData() {
   273 		if strings.HasPrefix(p, path) {
   282 		if strings.HasPrefix(p, path) {
   274 			m.mu.RUnlock()
   283 			m.mu.RUnlock()
   275 			m.mu.Lock()
   284 			m.mu.Lock()
   276 			delete(m.getData(), p)
   285 			delete(m.getData(), p)
   277 			m.mu.Unlock()
   286 			m.mu.Unlock()
   297 		m.unRegisterWithParent(oldname)
   306 		m.unRegisterWithParent(oldname)
   298 		fileData := m.getData()[oldname]
   307 		fileData := m.getData()[oldname]
   299 		delete(m.getData(), oldname)
   308 		delete(m.getData(), oldname)
   300 		mem.ChangeFileName(fileData, newname)
   309 		mem.ChangeFileName(fileData, newname)
   301 		m.getData()[newname] = fileData
   310 		m.getData()[newname] = fileData
   302 		m.registerWithParent(fileData)
   311 		m.registerWithParent(fileData, 0)
   303 		m.mu.Unlock()
   312 		m.mu.Unlock()
   304 		m.mu.RLock()
   313 		m.mu.RLock()
   305 	} else {
   314 	} else {
   306 		return &os.PathError{Op: "rename", Path: oldname, Err: ErrFileNotFound}
   315 		return &os.PathError{Op: "rename", Path: oldname, Err: ErrFileNotFound}
   307 	}
   316 	}
   308 	return nil
   317 	return nil
   309 }
   318 }
   310 
   319 
       
   320 func (m *MemMapFs) LstatIfPossible(name string) (os.FileInfo, bool, error) {
       
   321 	fileInfo, err := m.Stat(name)
       
   322 	return fileInfo, false, err
       
   323 }
       
   324 
   311 func (m *MemMapFs) Stat(name string) (os.FileInfo, error) {
   325 func (m *MemMapFs) Stat(name string) (os.FileInfo, error) {
   312 	f, err := m.Open(name)
   326 	f, err := m.Open(name)
   313 	if err != nil {
   327 	if err != nil {
   314 		return nil, err
   328 		return nil, err
   315 	}
   329 	}
   316 	fi := mem.GetFileInfo(f.(*mem.File).Data())
   330 	fi := mem.GetFileInfo(f.(*mem.File).Data())
   317 	return fi, nil
   331 	return fi, nil
   318 }
   332 }
   319 
   333 
   320 func (m *MemMapFs) Chmod(name string, mode os.FileMode) error {
   334 func (m *MemMapFs) Chmod(name string, mode os.FileMode) error {
   321 	name = normalizePath(name)
   335 	mode &= chmodBits
   322 
   336 
   323 	m.mu.RLock()
   337 	m.mu.RLock()
   324 	f, ok := m.getData()[name]
   338 	f, ok := m.getData()[name]
   325 	m.mu.RUnlock()
   339 	m.mu.RUnlock()
   326 	if !ok {
   340 	if !ok {
   327 		return &os.PathError{Op: "chmod", Path: name, Err: ErrFileNotFound}
   341 		return &os.PathError{Op: "chmod", Path: name, Err: ErrFileNotFound}
   328 	}
   342 	}
       
   343 	prevOtherBits := mem.GetFileInfo(f).Mode() & ^chmodBits
       
   344 
       
   345 	mode = prevOtherBits | mode
       
   346 	return m.setFileMode(name, mode)
       
   347 }
       
   348 
       
   349 func (m *MemMapFs) setFileMode(name string, mode os.FileMode) error {
       
   350 	name = normalizePath(name)
       
   351 
       
   352 	m.mu.RLock()
       
   353 	f, ok := m.getData()[name]
       
   354 	m.mu.RUnlock()
       
   355 	if !ok {
       
   356 		return &os.PathError{Op: "chmod", Path: name, Err: ErrFileNotFound}
       
   357 	}
   329 
   358 
   330 	m.mu.Lock()
   359 	m.mu.Lock()
   331 	mem.SetMode(f, mode)
   360 	mem.SetMode(f, mode)
   332 	m.mu.Unlock()
   361 	m.mu.Unlock()
       
   362 
       
   363 	return nil
       
   364 }
       
   365 
       
   366 func (m *MemMapFs) Chown(name string, uid, gid int) error {
       
   367 	name = normalizePath(name)
       
   368 
       
   369 	m.mu.RLock()
       
   370 	f, ok := m.getData()[name]
       
   371 	m.mu.RUnlock()
       
   372 	if !ok {
       
   373 		return &os.PathError{Op: "chown", Path: name, Err: ErrFileNotFound}
       
   374 	}
       
   375 
       
   376 	mem.SetUID(f, uid)
       
   377 	mem.SetGID(f, gid)
   333 
   378 
   334 	return nil
   379 	return nil
   335 }
   380 }
   336 
   381 
   337 func (m *MemMapFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
   382 func (m *MemMapFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
   355 	for _, x := range m.data {
   400 	for _, x := range m.data {
   356 		y := mem.FileInfo{FileData: x}
   401 		y := mem.FileInfo{FileData: x}
   357 		fmt.Println(x.Name(), y.Size())
   402 		fmt.Println(x.Name(), y.Size())
   358 	}
   403 	}
   359 }
   404 }
   360 
       
   361 // func debugMemMapList(fs Fs) {
       
   362 // 	if x, ok := fs.(*MemMapFs); ok {
       
   363 // 		x.List()
       
   364 // 	}
       
   365 // }