// filesContentManip manipulates with the content of the files // according to appropriate XML configuration file // Example: //<files> // <file> // <path>/etc/sysconfig/selinux</path> // <bkp_name>/etc/sysconfig/selinux.bkp</bkp_name> // <action>replace</action> // <old_pattern>SELINUX=\S+</old_pattern> // <new_pattern>SELINUX=disabled</new_pattern> // </file> // <file> // <path>/etc/passwd</path> // <bkp_name>/etc/passwd.bak</bkp_name> // <action>append</action> // <old_pattern></old_pattern> // <new_pattern>test:x:111:111::/root:/bin/bash</new_pattern> // </file> //</files> func filesContentManip(pathToXml, pathToSlash string) error { dataBuf, err := ioutil.ReadFile(pathToXml) if err != nil { return utils.FormatError(err) } fileContentStruct := FilesContent{} if err := xml.Unmarshal(dataBuf, &fileContentStruct); err != nil { return utils.FormatError(err) } for _, val := range fileContentStruct.FContent { targetPath := filepath.Join(pathToSlash, val.Path) if err != nil { return utils.FormatError(err) } finfo, err := os.Stat(targetPath) if err != nil { continue } if val.NewPattern == "" { return utils.FormatError(errors.New("configuration error - NewPattern is empty")) } if val.BkpName != "" { bkpFilePath := filepath.Join(pathToSlash, val.BkpName) if err := ioutils.CopyFile(targetPath, bkpFilePath, 0, -1, -1, false); err != nil { return utils.FormatError(err) } } fd, err := os.OpenFile(targetPath, os.O_RDWR|os.O_APPEND, finfo.Mode()) if err != nil { return utils.FormatError(err) } defer fd.Close() switch val.Action { // if we need to append to the file case ACTION_APPEND: if err := ioutils.AppendToFd(fd, val.NewPattern+"\n", val.NewPattern); err != nil { return utils.FormatError(err) } // if we need to replace a pattern case ACTION_REPLACE: if val.OldPattern == "" { return utils.FormatError(errors.New("configuration error - replace action is set but OldPattern is empty")) } if err := ioutils.FindAndReplaceFd(fd, val.OldPattern, val.NewPattern); err != nil { return utils.FormatError(err) } default: return utils.FormatError(errors.New(`FilesContentManip:configuration error - unsupported action`)) } } return nil }
// injectStuff modifies a RAW image "on-the-fly" // by injecting appropriate stuff to the mounted vHDD // 1) it receives src and dst directories paths // 2) it looks for a file inject.config inside the src directory // 3) in case the file found parses it and inject appropriate stuff // according to the file. // Example: //<inject_items> // <inject_item> // <name>file1</name> // <bkp_name>file1.bkp</bkp_name> // <action>upload</action> // <type>file</type> // <location>/opt</location> // <permissions>0755</permissions> // <owner_id>0</owner_id> // <group_id>0</group_id> // </inject_item> //</inject_items func injectManip(pathToXml, pathToSlash string) error { dataBuf, err := ioutil.ReadFile(pathToXml) if err != nil { return utils.FormatError(err) } itemsStruct := InjectItems{} if err := xml.Unmarshal(dataBuf, &itemsStruct); err != nil { return utils.FormatError(err) } for _, val := range itemsStruct.InjItems { baseDir := filepath.Dir(pathToXml) srcPath := baseDir + "/items/" + val.Name targetLocationPath := filepath.Join(pathToSlash, val.Location) dstPath := filepath.Join(targetLocationPath, val.Name) dstBkpPath := filepath.Join(targetLocationPath, val.BkpName) switch val.Action { case ACTION_REMOVE: if val.BkpName == "" { if err := ioutils.RemoveIfExists(true, dstPath); err != nil { return utils.FormatError(err) } } else { if _, err := os.Stat(dstPath); err == nil { if err := os.Rename(dstPath, dstBkpPath); err != nil { return utils.FormatError(err) } } } case ACTION_UPLOAD, ACTION_CREATE: switch val.Type { case ITEM_TYPE_FILE: if err := ioutils.CreateDirRecursively(targetLocationPath, 0755, val.UID, val.GID, false); err != nil { if err != os.ErrExist { return utils.FormatError(err) } } if val.Action == ACTION_UPLOAD { if val.BkpName != "" { if _, err := os.Stat(dstPath); err == nil { if err := os.Rename(dstPath, dstBkpPath); err != nil { return utils.FormatError(err) } } } if err := ioutils.CopyFile(srcPath, dstPath, 0, val.UID, val.GID, false); err != nil { return utils.FormatError(err) } } else { fd, err := os.Create(dstPath) if err != nil { return utils.FormatError(err) } fd.Close() } // FIXME: // we shuld use val.Permissions for setting permissions ,example // if err := CopyFile(srcFilePath, dstFilePath, // val.Permissions, val.UID, val.GID); err != nil { // return err //} // Currently , it copies permission flags from the source case ITEM_TYPE_DIR: if err := ioutils.CreateDirRecursively(filepath.Join(targetLocationPath, val.Name), val.Permissions, val.UID, val.GID, false); err != nil { return utils.FormatError(err) } if val.Action == ACTION_UPLOAD { if val.BkpName != "" { if _, err := os.Stat(dstPath); err == nil { if err := os.Rename(dstPath, dstBkpPath); err != nil { return utils.FormatError(err) } } } if err := ioutils.CopyDir(srcPath, dstPath); err != nil { return utils.FormatError(err) } } case ITEM_TYPE_LINK: if _, err := os.Stat(val.BkpName); err != nil { return utils.FormatError(err) } if err := ioutils.RemoveIfExists(false, dstPath); err != nil { return utils.FormatError(err) } if err := ioutils.CreateDirRecursively(targetLocationPath, val.Permissions, val.UID, val.GID, false); err != nil { return utils.FormatError(err) } if err := os.Symlink(val.BkpName, dstPath); err != nil { return utils.FormatError(err) } default: return utils.FormatError(errors.New("injectManip: configuration error - unexpected element type")) } default: return utils.FormatError(errors.New("injectManip: configuration error - unexpected action")) } } return nil }