<commit_before>/*
Copyright 2016 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package dockershim

import (
	"fmt"
	"io"
	"time"

	dockertypes "github.com/docker/engine-api/types"
	dockercontainer "github.com/docker/engine-api/types/container"
	dockerfilters "github.com/docker/engine-api/types/filters"
	dockerstrslice "github.com/docker/engine-api/types/strslice"
	"github.com/golang/glog"

	runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
	"k8s.io/kubernetes/pkg/kubelet/dockertools"
)

// ListContainers lists all containers matching the filter.
func (ds *dockerService) ListContainers(filter *runtimeApi.ContainerFilter) ([]*runtimeApi.Container, error) {
	opts := dockertypes.ContainerListOptions{All: true}

	opts.Filter = dockerfilters.NewArgs()
	f := newDockerFilter(&opts.Filter)
	// Add filter to get *only* (non-sandbox) containers.
	f.AddLabel(containerTypeLabelKey, containerTypeLabelContainer)

	if filter != nil {
		if filter.Id != nil {
			f.Add("id", filter.GetId())
		}
		if filter.State != nil {
			f.Add("status", toDockerContainerStatus(filter.GetState()))
		}
		if filter.PodSandboxId != nil {
			f.AddLabel(sandboxIDLabelKey, *filter.PodSandboxId)
		}

		if filter.LabelSelector != nil {
			for k, v := range filter.LabelSelector {
				f.AddLabel(k, v)
			}
		}
	}
	containers, err := ds.client.ListContainers(opts)
	if err != nil {
		return nil, err
	}
	// Convert docker to runtime api containers.
	result := []*runtimeApi.Container{}
	for i := range containers {
		c := containers[i]

		converted, err := toRuntimeAPIContainer(&c)
		if err != nil {
			glog.V(5).Infof("Unable to convert docker to runtime API container: %v", err)
			continue
		}

		result = append(result, converted)
	}
	return result, nil
}

// CreateContainer creates a new container in the given PodSandbox
// Note: docker doesn't use LogPath yet.
// TODO: check if the default values returned by the runtime API are ok.
func (ds *dockerService) CreateContainer(podSandboxID string, config *runtimeApi.ContainerConfig, sandboxConfig *runtimeApi.PodSandboxConfig) (string, error) {
	if config == nil {
		return "", fmt.Errorf("container config is nil")
	}
	if sandboxConfig == nil {
		return "", fmt.Errorf("sandbox config is nil for container %q", config.Metadata.GetName())
	}

	labels := makeLabels(config.GetLabels(), config.GetAnnotations())
	// Apply a the container type label.
	labels[containerTypeLabelKey] = containerTypeLabelContainer
	// Write the sandbox ID in the labels.
	labels[sandboxIDLabelKey] = podSandboxID

	image := ""
	if iSpec := config.GetImage(); iSpec != nil {
		image = iSpec.GetImage()
	}
	createConfig := dockertypes.ContainerCreateConfig{
		Name: makeContainerName(sandboxConfig, config),
		Config: &dockercontainer.Config{
			// TODO: set User.
			Entrypoint: dockerstrslice.StrSlice(config.GetCommand()),
			Cmd:        dockerstrslice.StrSlice(config.GetArgs()),
			Env:        generateEnvList(config.GetEnvs()),
			Image:      image,
			WorkingDir: config.GetWorkingDir(),
			Labels:     labels,
			// Interactive containers:
			OpenStdin: config.GetStdin(),
			StdinOnce: config.GetStdinOnce(),
			Tty:       config.GetTty(),
		},
	}

	// Fill the HostConfig.
	hc := &dockercontainer.HostConfig{
		Binds:          generateMountBindings(config.GetMounts()),
		ReadonlyRootfs: config.GetReadonlyRootfs(),
		Privileged:     config.GetPrivileged(),
	}

	// Apply options derived from the sandbox config.
	if lc := sandboxConfig.GetLinux(); lc != nil {
		// Apply Cgroup options.
		// TODO: Check if this works with per-pod cgroups.
		hc.CgroupParent = lc.GetCgroupParent()

		// Apply namespace options.
		sandboxNSMode := fmt.Sprintf("container:%v", podSandboxID)
		hc.NetworkMode = dockercontainer.NetworkMode(sandboxNSMode)
		hc.IpcMode = dockercontainer.IpcMode(sandboxNSMode)
		hc.UTSMode = ""
		hc.PidMode = ""

		nsOpts := lc.GetNamespaceOptions()
		if nsOpts != nil {
			if nsOpts.GetHostNetwork() {
				hc.UTSMode = namespaceModeHost
			}
			if nsOpts.GetHostPid() {
				hc.PidMode = namespaceModeHost
			}
		}
	}

	// Apply Linux-specific options if applicable.
	if lc := config.GetLinux(); lc != nil {
		// Apply resource options.
		// TODO: Check if the units are correct.
		// TODO: Can we assume the defaults are sane?
		rOpts := lc.GetResources()
		if rOpts != nil {
			hc.Resources = dockercontainer.Resources{
				Memory:     rOpts.GetMemoryLimitInBytes(),
				MemorySwap: -1, // Always disable memory swap.
				CPUShares:  rOpts.GetCpuShares(),
				CPUQuota:   rOpts.GetCpuQuota(),
				CPUPeriod:  rOpts.GetCpuPeriod(),
				// TODO: Need to set devices.
			}
			hc.OomScoreAdj = int(rOpts.GetOomScoreAdj())
		}
		// Note: ShmSize is handled in kube_docker_client.go
	}

	hc.SecurityOpt = []string{getSeccompOpts()}
	// TODO: Add or drop capabilities.

	createConfig.HostConfig = hc
	createResp, err := ds.client.CreateContainer(createConfig)
	if createResp != nil {
		return createResp.ID, err
	}
	return "", err
}

// StartContainer starts the container.
func (ds *dockerService) StartContainer(containerID string) error {
	return ds.client.StartContainer(containerID)
}

// StopContainer stops a running container with a grace period (i.e., timeout).
func (ds *dockerService) StopContainer(containerID string, timeout int64) error {
	return ds.client.StopContainer(containerID, int(timeout))
}

// RemoveContainer removes the container.
// TODO: If a container is still running, should we forcibly remove it?
func (ds *dockerService) RemoveContainer(containerID string) error {
	return ds.client.RemoveContainer(containerID, dockertypes.ContainerRemoveOptions{RemoveVolumes: true})
}

func getContainerTimestamps(r *dockertypes.ContainerJSON) (time.Time, time.Time, time.Time, error) {
	var createdAt, startedAt, finishedAt time.Time
	var err error

	createdAt, err = dockertools.ParseDockerTimestamp(r.Created)
	if err != nil {
		return createdAt, startedAt, finishedAt, err
	}
	startedAt, err = dockertools.ParseDockerTimestamp(r.State.StartedAt)
	if err != nil {
		return createdAt, startedAt, finishedAt, err
	}
	finishedAt, err = dockertools.ParseDockerTimestamp(r.State.FinishedAt)
	if err != nil {
		return createdAt, startedAt, finishedAt, err
	}
	return createdAt, startedAt, finishedAt, nil
}

// ContainerStatus returns the container status.
func (ds *dockerService) ContainerStatus(containerID string) (*runtimeApi.ContainerStatus, error) {
	r, err := ds.client.InspectContainer(containerID)
	if err != nil {
		return nil, err
	}

	// Parse the timstamps.
	createdAt, startedAt, finishedAt, err := getContainerTimestamps(r)
	if err != nil {
		return nil, fmt.Errorf("failed to parse timestamp for container %q: %v", containerID, err)
	}

	// Convert the mounts.
	mounts := []*runtimeApi.Mount{}
	for _, m := range r.Mounts {
		readonly := !m.RW
		mounts = append(mounts, &runtimeApi.Mount{
			Name:          &m.Name,
			HostPath:      &m.Source,
			ContainerPath: &m.Destination,
			Readonly:      &readonly,
			// Note: Can't set SeLinuxRelabel
		})
	}
	// Interpret container states.
	var state runtimeApi.ContainerState
	var reason, message string
	if r.State.Running {
		// Container is running.
		state = runtimeApi.ContainerState_RUNNING
	} else {
		// Container is *not* running. We need to get more details.
		//    * Case 1: container has run and exited with non-zero finishedAt
		//              time.
		//    * Case 2: container has failed to start; it has a zero finishedAt
		//              time, but a non-zero exit code.
		//    * Case 3: container has been created, but not started (yet).
		if !finishedAt.IsZero() { // Case 1
			state = runtimeApi.ContainerState_EXITED
			switch {
			case r.State.OOMKilled:
				// TODO: consider exposing OOMKilled via the runtimeAPI.
				// Note: if an application handles OOMKilled gracefully, the
				// exit code could be zero.
				reason = "OOMKilled"
			case r.State.ExitCode == 0:
				reason = "Completed"
			default:
				reason = "Error"
			}
		} else if r.State.ExitCode != 0 { // Case 2
			state = runtimeApi.ContainerState_EXITED
			// Adjust finshedAt and startedAt time to createdAt time to avoid
			// the confusion.
			finishedAt, startedAt = createdAt, createdAt
			reason = "ContainerCannotRun"
		} else { // Case 3
			state = runtimeApi.ContainerState_CREATED
		}
		message = r.State.Error
	}

	// Convert to unix timestamps.
	ct, st, ft := createdAt.Unix(), startedAt.Unix(), finishedAt.Unix()
	exitCode := int32(r.State.ExitCode)

	metadata, err := parseContainerName(r.Name)
	if err != nil {
		return nil, err
	}

	labels, annotations := extractLabels(r.Config.Labels)
	return &runtimeApi.ContainerStatus{
		Id:          &r.ID,
		Metadata:    metadata,
		Image:       &runtimeApi.ImageSpec{Image: &r.Config.Image},
		ImageRef:    &r.Image,
		Mounts:      mounts,
		ExitCode:    &exitCode,
		State:       &state,
		CreatedAt:   &ct,
		StartedAt:   &st,
		FinishedAt:  &ft,
		Reason:      &reason,
		Message:     &message,
		Labels:      labels,
		Annotations: annotations,
	}, nil
}

// Exec execute a command in the container.
// TODO: Need to handle terminal resizing before implementing this function.
// https://github.com/kubernetes/kubernetes/issues/29579.
func (ds *dockerService) Exec(containerID string, cmd []string, tty bool, stdin io.Reader, stdout, stderr io.WriteCloser) error {
	return fmt.Errorf("not implemented")
}
<commit_msg>Fix mount issue in dockershim.<commit_after>/*
Copyright 2016 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package dockershim

import (
	"fmt"
	"io"
	"time"

	dockertypes "github.com/docker/engine-api/types"
	dockercontainer "github.com/docker/engine-api/types/container"
	dockerfilters "github.com/docker/engine-api/types/filters"
	dockerstrslice "github.com/docker/engine-api/types/strslice"
	"github.com/golang/glog"

	runtimeApi "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
	"k8s.io/kubernetes/pkg/kubelet/dockertools"
)

// ListContainers lists all containers matching the filter.
func (ds *dockerService) ListContainers(filter *runtimeApi.ContainerFilter) ([]*runtimeApi.Container, error) {
	opts := dockertypes.ContainerListOptions{All: true}

	opts.Filter = dockerfilters.NewArgs()
	f := newDockerFilter(&opts.Filter)
	// Add filter to get *only* (non-sandbox) containers.
	f.AddLabel(containerTypeLabelKey, containerTypeLabelContainer)

	if filter != nil {
		if filter.Id != nil {
			f.Add("id", filter.GetId())
		}
		if filter.State != nil {
			f.Add("status", toDockerContainerStatus(filter.GetState()))
		}
		if filter.PodSandboxId != nil {
			f.AddLabel(sandboxIDLabelKey, *filter.PodSandboxId)
		}

		if filter.LabelSelector != nil {
			for k, v := range filter.LabelSelector {
				f.AddLabel(k, v)
			}
		}
	}
	containers, err := ds.client.ListContainers(opts)
	if err != nil {
		return nil, err
	}
	// Convert docker to runtime api containers.
	result := []*runtimeApi.Container{}
	for i := range containers {
		c := containers[i]

		converted, err := toRuntimeAPIContainer(&c)
		if err != nil {
			glog.V(5).Infof("Unable to convert docker to runtime API container: %v", err)
			continue
		}

		result = append(result, converted)
	}
	return result, nil
}

// CreateContainer creates a new container in the given PodSandbox
// Note: docker doesn't use LogPath yet.
// TODO: check if the default values returned by the runtime API are ok.
func (ds *dockerService) CreateContainer(podSandboxID string, config *runtimeApi.ContainerConfig, sandboxConfig *runtimeApi.PodSandboxConfig) (string, error) {
	if config == nil {
		return "", fmt.Errorf("container config is nil")
	}
	if sandboxConfig == nil {
		return "", fmt.Errorf("sandbox config is nil for container %q", config.Metadata.GetName())
	}

	labels := makeLabels(config.GetLabels(), config.GetAnnotations())
	// Apply a the container type label.
	labels[containerTypeLabelKey] = containerTypeLabelContainer
	// Write the sandbox ID in the labels.
	labels[sandboxIDLabelKey] = podSandboxID

	image := ""
	if iSpec := config.GetImage(); iSpec != nil {
		image = iSpec.GetImage()
	}
	createConfig := dockertypes.ContainerCreateConfig{
		Name: makeContainerName(sandboxConfig, config),
		Config: &dockercontainer.Config{
			// TODO: set User.
			Entrypoint: dockerstrslice.StrSlice(config.GetCommand()),
			Cmd:        dockerstrslice.StrSlice(config.GetArgs()),
			Env:        generateEnvList(config.GetEnvs()),
			Image:      image,
			WorkingDir: config.GetWorkingDir(),
			Labels:     labels,
			// Interactive containers:
			OpenStdin: config.GetStdin(),
			StdinOnce: config.GetStdinOnce(),
			Tty:       config.GetTty(),
		},
	}

	// Fill the HostConfig.
	hc := &dockercontainer.HostConfig{
		Binds:          generateMountBindings(config.GetMounts()),
		ReadonlyRootfs: config.GetReadonlyRootfs(),
		Privileged:     config.GetPrivileged(),
	}

	// Apply options derived from the sandbox config.
	if lc := sandboxConfig.GetLinux(); lc != nil {
		// Apply Cgroup options.
		// TODO: Check if this works with per-pod cgroups.
		hc.CgroupParent = lc.GetCgroupParent()

		// Apply namespace options.
		sandboxNSMode := fmt.Sprintf("container:%v", podSandboxID)
		hc.NetworkMode = dockercontainer.NetworkMode(sandboxNSMode)
		hc.IpcMode = dockercontainer.IpcMode(sandboxNSMode)
		hc.UTSMode = ""
		hc.PidMode = ""

		nsOpts := lc.GetNamespaceOptions()
		if nsOpts != nil {
			if nsOpts.GetHostNetwork() {
				hc.UTSMode = namespaceModeHost
			}
			if nsOpts.GetHostPid() {
				hc.PidMode = namespaceModeHost
			}
		}
	}

	// Apply Linux-specific options if applicable.
	if lc := config.GetLinux(); lc != nil {
		// Apply resource options.
		// TODO: Check if the units are correct.
		// TODO: Can we assume the defaults are sane?
		rOpts := lc.GetResources()
		if rOpts != nil {
			hc.Resources = dockercontainer.Resources{
				Memory:     rOpts.GetMemoryLimitInBytes(),
				MemorySwap: -1, // Always disable memory swap.
				CPUShares:  rOpts.GetCpuShares(),
				CPUQuota:   rOpts.GetCpuQuota(),
				CPUPeriod:  rOpts.GetCpuPeriod(),
				// TODO: Need to set devices.
			}
			hc.OomScoreAdj = int(rOpts.GetOomScoreAdj())
		}
		// Note: ShmSize is handled in kube_docker_client.go
	}

	hc.SecurityOpt = []string{getSeccompOpts()}
	// TODO: Add or drop capabilities.

	createConfig.HostConfig = hc
	createResp, err := ds.client.CreateContainer(createConfig)
	if createResp != nil {
		return createResp.ID, err
	}
	return "", err
}

// StartContainer starts the container.
func (ds *dockerService) StartContainer(containerID string) error {
	return ds.client.StartContainer(containerID)
}

// StopContainer stops a running container with a grace period (i.e., timeout).
func (ds *dockerService) StopContainer(containerID string, timeout int64) error {
	return ds.client.StopContainer(containerID, int(timeout))
}

// RemoveContainer removes the container.
// TODO: If a container is still running, should we forcibly remove it?
func (ds *dockerService) RemoveContainer(containerID string) error {
	return ds.client.RemoveContainer(containerID, dockertypes.ContainerRemoveOptions{RemoveVolumes: true})
}

func getContainerTimestamps(r *dockertypes.ContainerJSON) (time.Time, time.Time, time.Time, error) {
	var createdAt, startedAt, finishedAt time.Time
	var err error

	createdAt, err = dockertools.ParseDockerTimestamp(r.Created)
	if err != nil {
		return createdAt, startedAt, finishedAt, err
	}
	startedAt, err = dockertools.ParseDockerTimestamp(r.State.StartedAt)
	if err != nil {
		return createdAt, startedAt, finishedAt, err
	}
	finishedAt, err = dockertools.ParseDockerTimestamp(r.State.FinishedAt)
	if err != nil {
		return createdAt, startedAt, finishedAt, err
	}
	return createdAt, startedAt, finishedAt, nil
}

// ContainerStatus returns the container status.
func (ds *dockerService) ContainerStatus(containerID string) (*runtimeApi.ContainerStatus, error) {
	r, err := ds.client.InspectContainer(containerID)
	if err != nil {
		return nil, err
	}

	// Parse the timstamps.
	createdAt, startedAt, finishedAt, err := getContainerTimestamps(r)
	if err != nil {
		return nil, fmt.Errorf("failed to parse timestamp for container %q: %v", containerID, err)
	}

	// Convert the mounts.
	mounts := []*runtimeApi.Mount{}
	for i := range r.Mounts {
		m := r.Mounts[i]
		readonly := !m.RW
		mounts = append(mounts, &runtimeApi.Mount{
			Name:          &m.Name,
			HostPath:      &m.Source,
			ContainerPath: &m.Destination,
			Readonly:      &readonly,
			// Note: Can't set SeLinuxRelabel
		})
	}
	// Interpret container states.
	var state runtimeApi.ContainerState
	var reason, message string
	if r.State.Running {
		// Container is running.
		state = runtimeApi.ContainerState_RUNNING
	} else {
		// Container is *not* running. We need to get more details.
		//    * Case 1: container has run and exited with non-zero finishedAt
		//              time.
		//    * Case 2: container has failed to start; it has a zero finishedAt
		//              time, but a non-zero exit code.
		//    * Case 3: container has been created, but not started (yet).
		if !finishedAt.IsZero() { // Case 1
			state = runtimeApi.ContainerState_EXITED
			switch {
			case r.State.OOMKilled:
				// TODO: consider exposing OOMKilled via the runtimeAPI.
				// Note: if an application handles OOMKilled gracefully, the
				// exit code could be zero.
				reason = "OOMKilled"
			case r.State.ExitCode == 0:
				reason = "Completed"
			default:
				reason = "Error"
			}
		} else if r.State.ExitCode != 0 { // Case 2
			state = runtimeApi.ContainerState_EXITED
			// Adjust finshedAt and startedAt time to createdAt time to avoid
			// the confusion.
			finishedAt, startedAt = createdAt, createdAt
			reason = "ContainerCannotRun"
		} else { // Case 3
			state = runtimeApi.ContainerState_CREATED
		}
		message = r.State.Error
	}

	// Convert to unix timestamps.
	ct, st, ft := createdAt.Unix(), startedAt.Unix(), finishedAt.Unix()
	exitCode := int32(r.State.ExitCode)

	metadata, err := parseContainerName(r.Name)
	if err != nil {
		return nil, err
	}

	labels, annotations := extractLabels(r.Config.Labels)
	return &runtimeApi.ContainerStatus{
		Id:          &r.ID,
		Metadata:    metadata,
		Image:       &runtimeApi.ImageSpec{Image: &r.Config.Image},
		ImageRef:    &r.Image,
		Mounts:      mounts,
		ExitCode:    &exitCode,
		State:       &state,
		CreatedAt:   &ct,
		StartedAt:   &st,
		FinishedAt:  &ft,
		Reason:      &reason,
		Message:     &message,
		Labels:      labels,
		Annotations: annotations,
	}, nil
}

// Exec execute a command in the container.
// TODO: Need to handle terminal resizing before implementing this function.
// https://github.com/kubernetes/kubernetes/issues/29579.
func (ds *dockerService) Exec(containerID string, cmd []string, tty bool, stdin io.Reader, stdout, stderr io.WriteCloser) error {
	return fmt.Errorf("not implemented")
}
<|endoftext|>


<commit_before>// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package admin defines an administrative interface into the fleetspeak system.
package admin

import (
	"bytes"
	"errors"
	"fmt"

	"context"

	"github.com/google/fleetspeak/fleetspeak/src/common"
	"github.com/google/fleetspeak/fleetspeak/src/server/db"

	fspb "github.com/google/fleetspeak/fleetspeak/src/common/proto/fleetspeak"
	sgrpc "github.com/google/fleetspeak/fleetspeak/src/server/proto/fleetspeak_server"
	spb "github.com/google/fleetspeak/fleetspeak/src/server/proto/fleetspeak_server"
)

// NewServer returns an admin_grpc.AdminServer which performs operations using
// the provided db.Store.
func NewServer(s db.Store) sgrpc.AdminServer {
	return adminServer{s}
}

type adminServer struct {
	store db.Store
}

func (s adminServer) CreateBroadcast(ctx context.Context, req *spb.CreateBroadcastRequest) (*fspb.EmptyMessage, error) {
	if err := s.store.CreateBroadcast(ctx, req.Broadcast, req.Limit); err != nil {
		return nil, err
	}
	return &fspb.EmptyMessage{}, nil
}

func (s adminServer) ListActiveBroadcasts(ctx context.Context, req *spb.ListActiveBroadcastsRequest) (*spb.ListActiveBroadcastsResponse, error) {
	var ret spb.ListActiveBroadcastsResponse
	bis, err := s.store.ListActiveBroadcasts(ctx)
	if err != nil {
		return nil, err
	}
	for _, bi := range bis {
		if req.ServiceName != "" && req.ServiceName != bi.Broadcast.Source.ServiceName {
			continue
		}
		ret.Broadcasts = append(ret.Broadcasts, bi.Broadcast)
	}
	return &ret, nil
}

func (s adminServer) GetMessageStatus(ctx context.Context, req *spb.GetMessageStatusRequest) (*spb.GetMessageStatusResponse, error) {
	mid, err := common.BytesToMessageID(req.MessageId)
	if err != nil {
		return nil, err
	}

	msgs, err := s.store.GetMessages(ctx, []common.MessageID{mid}, false)
	if err != nil {
		if s.store.IsNotFound(err) {
			return &spb.GetMessageStatusResponse{}, nil
		}
		return nil, err
	}
	if len(msgs) != 1 {
		return nil, fmt.Errorf("Internal error, expected 1 message, got %d", len(msgs))
	}

	return &spb.GetMessageStatusResponse{
			CreationTime: msgs[0].CreationTime,
			Result:       msgs[0].Result},
		nil
}

func (s adminServer) ListClients(ctx context.Context, req *spb.ListClientsRequest) (*spb.ListClientsResponse, error) {
	ids := make([]common.ClientID, 0, len(req.ClientIds))
	for i, b := range req.ClientIds {
		id, err := common.BytesToClientID(b)
		if err != nil {
			return nil, fmt.Errorf("unable to parse id [%d]: %v", i, err)
		}
		ids = append(ids, id)
	}
	clients, err := s.store.ListClients(ctx, ids)
	if err != nil {
		return nil, err
	}

	return &spb.ListClientsResponse{
		Clients: clients,
	}, nil
}

// InsertMessage implements sgrpc.AdminServer.
func (s adminServer) InsertMessage(ctx context.Context, m *fspb.Message) (*fspb.EmptyMessage, error) {
	// At this point, we mostly trust the message we get, but do some basic
	// sanity checks and generate missing metadata.
	if m.Destination == nil || m.Destination.ServiceName == "" {
		return nil, errors.New("message must have Destination")
	}
	if m.Source == nil || m.Source.ServiceName == "" {
		return nil, errors.New("message must have Source")
	}
	if len(m.MessageId) == 0 {
		id, err := common.RandomMessageID()
		if err != nil {
			return nil, fmt.Errorf("unable to create random MessageID: %v", err)
		}
		m.MessageId = id.Bytes()
	}
	if m.CreationTime == nil {
		m.CreationTime = db.NowProto()
	}
	if err := s.store.StoreMessages(ctx, []*fspb.Message{m}, ""); err != nil {
		return nil, err
	}
	return &fspb.EmptyMessage{}, nil
}

// StoreFile implements sgrpc.AdminServer.
func (s adminServer) StoreFile(ctx context.Context, req *spb.StoreFileRequest) (*fspb.EmptyMessage, error) {
	if req.ServiceName == "" || req.FileName == "" {
		return nil, errors.New("file must have service_name and file_name")
	}
	if err := s.store.StoreFile(ctx, req.ServiceName, req.FileName, bytes.NewReader(req.Data)); err != nil {
		return nil, err
	}
	return &fspb.EmptyMessage{}, nil
}

// KeepAlive implements sgrpc.AdminServer.
func (s adminServer) KeepAlive(ctx context.Context, _ *fspb.EmptyMessage) (*fspb.EmptyMessage, error) {
	return &fspb.EmptyMessage{}, nil
}
<commit_msg>Implement ListClientContacts admin call.<commit_after>// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package admin defines an administrative interface into the fleetspeak system.
package admin

import (
	"bytes"
	"errors"
	"fmt"

	"context"

	"github.com/google/fleetspeak/fleetspeak/src/common"
	"github.com/google/fleetspeak/fleetspeak/src/server/db"

	fspb "github.com/google/fleetspeak/fleetspeak/src/common/proto/fleetspeak"
	sgrpc "github.com/google/fleetspeak/fleetspeak/src/server/proto/fleetspeak_server"
	spb "github.com/google/fleetspeak/fleetspeak/src/server/proto/fleetspeak_server"
)

// NewServer returns an admin_grpc.AdminServer which performs operations using
// the provided db.Store.
func NewServer(s db.Store) sgrpc.AdminServer {
	return adminServer{s}
}

type adminServer struct {
	store db.Store
}

func (s adminServer) CreateBroadcast(ctx context.Context, req *spb.CreateBroadcastRequest) (*fspb.EmptyMessage, error) {
	if err := s.store.CreateBroadcast(ctx, req.Broadcast, req.Limit); err != nil {
		return nil, err
	}
	return &fspb.EmptyMessage{}, nil
}

func (s adminServer) ListActiveBroadcasts(ctx context.Context, req *spb.ListActiveBroadcastsRequest) (*spb.ListActiveBroadcastsResponse, error) {
	var ret spb.ListActiveBroadcastsResponse
	bis, err := s.store.ListActiveBroadcasts(ctx)
	if err != nil {
		return nil, err
	}
	for _, bi := range bis {
		if req.ServiceName != "" && req.ServiceName != bi.Broadcast.Source.ServiceName {
			continue
		}
		ret.Broadcasts = append(ret.Broadcasts, bi.Broadcast)
	}
	return &ret, nil
}

func (s adminServer) GetMessageStatus(ctx context.Context, req *spb.GetMessageStatusRequest) (*spb.GetMessageStatusResponse, error) {
	mid, err := common.BytesToMessageID(req.MessageId)
	if err != nil {
		return nil, err
	}

	msgs, err := s.store.GetMessages(ctx, []common.MessageID{mid}, false)
	if err != nil {
		if s.store.IsNotFound(err) {
			return &spb.GetMessageStatusResponse{}, nil
		}
		return nil, err
	}
	if len(msgs) != 1 {
		return nil, fmt.Errorf("Internal error, expected 1 message, got %d", len(msgs))
	}

	return &spb.GetMessageStatusResponse{
			CreationTime: msgs[0].CreationTime,
			Result:       msgs[0].Result},
		nil
}

func (s adminServer) ListClients(ctx context.Context, req *spb.ListClientsRequest) (*spb.ListClientsResponse, error) {
	ids := make([]common.ClientID, 0, len(req.ClientIds))
	for i, b := range req.ClientIds {
		id, err := common.BytesToClientID(b)
		if err != nil {
			return nil, fmt.Errorf("unable to parse id [%d]: %v", i, err)
		}
		ids = append(ids, id)
	}
	clients, err := s.store.ListClients(ctx, ids)
	if err != nil {
		return nil, err
	}

	return &spb.ListClientsResponse{
		Clients: clients,
	}, nil
}

func (s adminServer) ListClientContacts(ctx context.Context, req *spb.ListClientContactsRequest) (*spb.ListClientContactsResponse, error) {
	id, err := common.BytesToClientID(req.ClientId)
	if err != nil {
		return nil, fmt.Errorf("unable to parse id [%d]: %v", req.ClientId, err)
	}

	contacts, err := s.store.ListClientContacts(ctx, id)
	if err != nil {
		return nil, err
	}
	return &spb.ListClientContactsResponse{
		Contacts: contacts,
	}, nil
}

// InsertMessage implements sgrpc.AdminServer.
func (s adminServer) InsertMessage(ctx context.Context, m *fspb.Message) (*fspb.EmptyMessage, error) {
	// At this point, we mostly trust the message we get, but do some basic
	// sanity checks and generate missing metadata.
	if m.Destination == nil || m.Destination.ServiceName == "" {
		return nil, errors.New("message must have Destination")
	}
	if m.Source == nil || m.Source.ServiceName == "" {
		return nil, errors.New("message must have Source")
	}
	if len(m.MessageId) == 0 {
		id, err := common.RandomMessageID()
		if err != nil {
			return nil, fmt.Errorf("unable to create random MessageID: %v", err)
		}
		m.MessageId = id.Bytes()
	}
	if m.CreationTime == nil {
		m.CreationTime = db.NowProto()
	}
	if err := s.store.StoreMessages(ctx, []*fspb.Message{m}, ""); err != nil {
		return nil, err
	}
	return &fspb.EmptyMessage{}, nil
}

// StoreFile implements sgrpc.AdminServer.
func (s adminServer) StoreFile(ctx context.Context, req *spb.StoreFileRequest) (*fspb.EmptyMessage, error) {
	if req.ServiceName == "" || req.FileName == "" {
		return nil, errors.New("file must have service_name and file_name")
	}
	if err := s.store.StoreFile(ctx, req.ServiceName, req.FileName, bytes.NewReader(req.Data)); err != nil {
		return nil, err
	}
	return &fspb.EmptyMessage{}, nil
}

// KeepAlive implements sgrpc.AdminServer.
func (s adminServer) KeepAlive(ctx context.Context, _ *fspb.EmptyMessage) (*fspb.EmptyMessage, error) {
	return &fspb.EmptyMessage{}, nil
}
<|endoftext|>


<commit_before>// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package big

import "testing"

type setStringTest struct {
	in, out string
}

var setStringTests = []setStringTest{
	setStringTest{"0", "0"},
	setStringTest{"1", "1"},
	setStringTest{"-1", "-1"},
	setStringTest{"2/4", "1/2"},
	setStringTest{".25", "1/4"},
	setStringTest{"-1/5", "-1/5"},
}

func TestRatSetString(t *testing.T) {
	for i, test := range setStringTests {
		x, _ := new(Rat).SetString(test.in)

		if x.String() != test.out {
			t.Errorf("#%d got %s want %s", i, x.String(), test.out)
		}
	}
}

type floatStringTest struct {
	in   string
	prec int
	out  string
}

var floatStringTests = []floatStringTest{
	floatStringTest{"0", 0, "0"},
	floatStringTest{"0", 4, "0"},
	floatStringTest{"1", 0, "1"},
	floatStringTest{"1", 2, "1"},
	floatStringTest{"-1", 0, "-1"},
	floatStringTest{".25", 2, "0.25"},
	floatStringTest{".25", 1, "0.3"},
	floatStringTest{"-1/3", 3, "-0.333"},
	floatStringTest{"-2/3", 4, "-0.6667"},
}

func TestFloatString(t *testing.T) {
	for i, test := range floatStringTests {
		x, _ := new(Rat).SetString(test.in)

		if x.FloatString(test.prec) != test.out {
			t.Errorf("#%d got %s want %s", i, x.FloatString(test.prec), test.out)
		}
	}
}

type ratCmpTest struct {
	rat1, rat2 string
	out        int
}

var ratCmpTests = []ratCmpTest{
	ratCmpTest{"0", "0/1", 0},
	ratCmpTest{"1/1", "1", 0},
	ratCmpTest{"-1", "-2/2", 0},
	ratCmpTest{"1", "0", 1},
	ratCmpTest{"0/1", "1/1", -1},
	ratCmpTest{"-5/1434770811533343057144", "-5/1434770811533343057145", -1},
	ratCmpTest{"49832350382626108453/8964749413", "49832350382626108454/8964749413", -1},
	ratCmpTest{"-37414950961700930/7204075375675961", "37414950961700930/7204075375675961", -1},
	ratCmpTest{"37414950961700930/7204075375675961", "74829901923401860/14408150751351922", 0},
}

func TestRatCmp(t *testing.T) {
	for i, test := range ratCmpTests {
		x, _ := new(Rat).SetString(test.rat1)
		y, _ := new(Rat).SetString(test.rat2)

		out := x.Cmp(y)
		if out != test.out {
			t.Errorf("#%d got out = %v; want %v", i, out, test.out)
		}
	}
}

type ratBinFun func(z, x, y *Rat) *Rat
type ratBinArg struct {
	x   string
	y   string
	out string
}

func testRatBin(t *testing.T, f ratBinFun, a []ratBinArg) {
	for i, test := range a {
		x, _ := NewRat(0, 1).SetString(test.x)
		y, _ := NewRat(0, 1).SetString(test.y)
		expected, _ := NewRat(0, 1).SetString(test.out)
		out := f(NewRat(0, 1), x, y)

		if out.Cmp(expected) != 0 {
			t.Errorf("#%d got %s want %s", i, out, expected)
		}
	}
}

var ratAddTests = []ratBinArg{
	ratBinArg{"0", "0", "0"},
	ratBinArg{"0", "1", "1"},
	ratBinArg{"-1", "0", "-1"},
	ratBinArg{"-1", "1", "0"},
	ratBinArg{"1", "1", "2"},
	ratBinArg{"1/2", "1/2", "1"},
	ratBinArg{"1/4", "1/3", "7/12"},
	ratBinArg{"2/5", "-14/3", "-64/15"},
	ratBinArg{"4707/49292519774798173060", "-3367/70976135186689855734", "84058377121001851123459/1749296273614329067191168098769082663020"},
	ratBinArg{"-61204110018146728334/3", "-31052192278051565633/2", "-215564796870448153567/6"},
}

func TestRatAdd(t *testing.T) {
	testRatBin(t, (*Rat).Add, ratAddTests)
}

var ratSubTests = []ratBinArg{
	ratBinArg{"0", "0", "0"},
	ratBinArg{"0", "1", "-1"},
	ratBinArg{"-1", "0", "-1"},
	ratBinArg{"-1", "1", "-2"},
	ratBinArg{"1", "1", "0"},
	ratBinArg{"1/2", "1/3", "1/6"},
	ratBinArg{"1/4", "1/3", "-1/12"},
	ratBinArg{"2/5", "-14/3", "76/15"},
	ratBinArg{"4707/49292519774798173060", "-3367/70976135186689855734", "250026291202747299816479/1749296273614329067191168098769082663020"},
	ratBinArg{"-27/133467566250814981", "-18/31750379913563777419", "-854857841473707320655/4237645934602118692642972629634714039"},
	ratBinArg{"27674141753240653/30123979153216", "-19948846211000086/637313996471", "618575745270541348005638912139/19198433543745179392300736"},
}

func TestRatSub(t *testing.T) {
	testRatBin(t, (*Rat).Sub, ratSubTests)
}

var ratMulTests = []ratBinArg{
	ratBinArg{"0", "0", "0"},
	ratBinArg{"0", "1", "0"},
	ratBinArg{"-1", "0", "0"},
	ratBinArg{"-1", "1", "-1"},
	ratBinArg{"1", "1", "1"},
	ratBinArg{"1/2", "1/2", "1/4"},
	ratBinArg{"1/4", "1/3", "1/12"},
	ratBinArg{"2/5", "-14/3", "-28/15"},
	ratBinArg{"-3/26206484091896184128", "5/2848423294177090248", "-5/24882386581946146755650075889827061248"},
	ratBinArg{"26946729/330400702820", "41563965/225583428284", "224002580204097/14906584649915733312176"},
	ratBinArg{"-8259900599013409474/7", "-84829337473700364773/56707961321161574960", "350340947706464153265156004876107029701/198477864624065512360"},
}

func TestRatMul(t *testing.T) {
	testRatBin(t, (*Rat).Mul, ratMulTests)
}

var ratQuoTests = []ratBinArg{
	ratBinArg{"0", "1", "0"},
	ratBinArg{"0", "-1", "0"},
	ratBinArg{"-1", "1", "-1"},
	ratBinArg{"1", "1", "1"},
	ratBinArg{"1/2", "1/2", "1"},
	ratBinArg{"1/4", "1/3", "3/4"},
	ratBinArg{"2/5", "-14/3", "-3/35"},
	ratBinArg{"808/45524274987585732633", "29/712593081308", "575775209696864/1320203974639986246357"},
	ratBinArg{"8967230/3296219033", "6269770/1992362624741777", "1786597389946320496771/2066653520653241"},
	ratBinArg{"-3784609207827/3426986245", "9381566963714/9633539", "-36459180403360509753/32150500941194292113930"},
}

func TestRatQuo(t *testing.T) {
	testRatBin(t, (*Rat).Quo, ratQuoTests)
}
<commit_msg>big: Rat test improvements<commit_after>// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package big

import "testing"

type setStringTest struct {
	in, out string
	ok      bool
}

var setStringTests = []setStringTest{
	setStringTest{"0", "0", true},
	setStringTest{"-0", "0", true},
	setStringTest{"1", "1", true},
	setStringTest{"-1", "-1", true},
	setStringTest{in: "r", ok: false},
	setStringTest{in: "a/b", ok: false},
	setStringTest{in: "a.b", ok: false},
	setStringTest{"-0.1", "-1/10", true},
	setStringTest{"-.1", "-1/10", true},
	setStringTest{"2/4", "1/2", true},
	setStringTest{".25", "1/4", true},
	setStringTest{"-1/5", "-1/5", true},
	setStringTest{"884243222337379604041632732738665534", "884243222337379604041632732738665534", true},
	setStringTest{"53/70893980658822810696", "53/70893980658822810696", true},
	setStringTest{"106/141787961317645621392", "53/70893980658822810696", true},
	setStringTest{"204211327800791583.81095", "4084226556015831676219/20000", true},
}

func TestRatSetString(t *testing.T) {
	for i, test := range setStringTests {
		x, ok := new(Rat).SetString(test.in)

		if ok != test.ok || ok && x.String() != test.out {
			t.Errorf("#%d got %s want %s", i, x.String(), test.out)
		}
	}
}

type floatStringTest struct {
	in   string
	prec int
	out  string
}

var floatStringTests = []floatStringTest{
	floatStringTest{"0", 0, "0"},
	floatStringTest{"0", 4, "0"},
	floatStringTest{"1", 0, "1"},
	floatStringTest{"1", 2, "1"},
	floatStringTest{"-1", 0, "-1"},
	floatStringTest{".25", 2, "0.25"},
	floatStringTest{".25", 1, "0.3"},
	floatStringTest{"-1/3", 3, "-0.333"},
	floatStringTest{"-2/3", 4, "-0.6667"},
}

func TestFloatString(t *testing.T) {
	for i, test := range floatStringTests {
		x, _ := new(Rat).SetString(test.in)

		if x.FloatString(test.prec) != test.out {
			t.Errorf("#%d got %s want %s", i, x.FloatString(test.prec), test.out)
		}
	}
}

type ratCmpTest struct {
	rat1, rat2 string
	out        int
}

var ratCmpTests = []ratCmpTest{
	ratCmpTest{"0", "0/1", 0},
	ratCmpTest{"1/1", "1", 0},
	ratCmpTest{"-1", "-2/2", 0},
	ratCmpTest{"1", "0", 1},
	ratCmpTest{"0/1", "1/1", -1},
	ratCmpTest{"-5/1434770811533343057144", "-5/1434770811533343057145", -1},
	ratCmpTest{"49832350382626108453/8964749413", "49832350382626108454/8964749413", -1},
	ratCmpTest{"-37414950961700930/7204075375675961", "37414950961700930/7204075375675961", -1},
	ratCmpTest{"37414950961700930/7204075375675961", "74829901923401860/14408150751351922", 0},
}

func TestRatCmp(t *testing.T) {
	for i, test := range ratCmpTests {
		x, _ := new(Rat).SetString(test.rat1)
		y, _ := new(Rat).SetString(test.rat2)

		out := x.Cmp(y)
		if out != test.out {
			t.Errorf("#%d got out = %v; want %v", i, out, test.out)
		}
	}
}

type ratBinFun func(z, x, y *Rat) *Rat
type ratBinArg struct {
	x, y, z string
}

func testRatBin(t *testing.T, i int, name string, f ratBinFun, a ratBinArg) {
	x, _ := NewRat(0, 1).SetString(a.x)
	y, _ := NewRat(0, 1).SetString(a.y)
	z, _ := NewRat(0, 1).SetString(a.z)
	out := f(NewRat(0, 1), x, y)

	if out.Cmp(z) != 0 {
		t.Errorf("%s #%d got %s want %s", name, i, out, z)
	}
}

type ratBinTest struct {
	x, y      string
	sum, prod string
}

var ratBinTests = []ratBinTest{
	ratBinTest{"0", "0", "0", "0"},
	ratBinTest{"0", "1", "1", "0"},
	ratBinTest{"-1", "0", "-1", "0"},
	ratBinTest{"-1", "1", "0", "-1"},
	ratBinTest{"1", "1", "2", "1"},
	ratBinTest{"1/2", "1/2", "1", "1/4"},
	ratBinTest{"1/4", "1/3", "7/12", "1/12"},
	ratBinTest{"2/5", "-14/3", "-64/15", "-28/15"},
	ratBinTest{"4707/49292519774798173060", "-3367/70976135186689855734", "84058377121001851123459/1749296273614329067191168098769082663020", "-1760941/388732505247628681598037355282018369560"},
	ratBinTest{"-61204110018146728334/3", "-31052192278051565633/2", "-215564796870448153567/6", "950260896245257153059642991192710872711/3"},
	ratBinTest{"-854857841473707320655/4237645934602118692642972629634714039", "-18/31750379913563777419", "-27/133467566250814981", "15387441146526731771790/134546868362786310073779084329032722548987800600710485341"},
	ratBinTest{"618575745270541348005638912139/19198433543745179392300736", "-19948846211000086/637313996471", "27674141753240653/30123979153216", "-6169936206128396568797607742807090270137721977/6117715203873571641674006593837351328"},
	ratBinTest{"-3/26206484091896184128", "5/2848423294177090248", "15310893822118706237/9330894968229805033368778458685147968", "-5/24882386581946146755650075889827061248"},
	ratBinTest{"26946729/330400702820", "41563965/225583428284", "1238218672302860271/4658307703098666660055", "224002580204097/14906584649915733312176"},
	ratBinTest{"-8259900599013409474/7", "-84829337473700364773/56707961321161574960", "-468402123685491748914621885145127724451/396955729248131024720", "350340947706464153265156004876107029701/198477864624065512360"},
	ratBinTest{"575775209696864/1320203974639986246357", "29/712593081308", "410331716733912717985762465/940768218243776489278275419794956", "808/45524274987585732633"},
	ratBinTest{"1786597389946320496771/2066653520653241", "6269770/1992362624741777", "3559549865190272133656109052308126637/4117523232840525481453983149257", "8967230/3296219033"},
	ratBinTest{"-36459180403360509753/32150500941194292113930", "9381566963714/9633539", "301622077145533298008420642898530153/309723104686531919656937098270", "-3784609207827/3426986245"},
}

func TestRatBin(t *testing.T) {
	for i, test := range ratBinTests {
		arg := ratBinArg{test.x, test.y, test.sum}
		testRatBin(t, i, "Add", (*Rat).Add, arg)

		arg = ratBinArg{test.y, test.x, test.sum}
		testRatBin(t, i, "Add symmetric", (*Rat).Add, arg)

		arg = ratBinArg{test.sum, test.x, test.y}
		testRatBin(t, i, "Sub", (*Rat).Sub, arg)

		arg = ratBinArg{test.sum, test.y, test.x}
		testRatBin(t, i, "Sub symmetric", (*Rat).Sub, arg)

		arg = ratBinArg{test.x, test.y, test.prod}
		testRatBin(t, i, "Mul", (*Rat).Mul, arg)

		arg = ratBinArg{test.y, test.x, test.prod}
		testRatBin(t, i, "Mul symmetric", (*Rat).Mul, arg)

		if test.x != "0" {
			arg = ratBinArg{test.prod, test.x, test.y}
			testRatBin(t, i, "Quo", (*Rat).Quo, arg)
		}

		if test.y != "0" {
			arg = ratBinArg{test.prod, test.y, test.x}
			testRatBin(t, i, "Quo symmetric", (*Rat).Quo, arg)
		}
	}
}
<|endoftext|>


<commit_before>package mit

import (
	"database/sql"
	"encoding/json"
	"strings"

	"github.com/thatoddmailbox/touchstone-client/touchstone"

	"github.com/MyHomeworkSpace/api-server/data"
	"github.com/MyHomeworkSpace/api-server/schools"
)

func clearUserData(tx *sql.Tx, user *data.User) error {
	// clear away anything that is in the db
	_, err := tx.Exec("DELETE FROM mit_classes WHERE userId = ?", user.ID)
	if err != nil {
		return err
	}

	return nil
}

func (s *school) Enroll(tx *sql.Tx, user *data.User, params map[string]interface{}) (map[string]interface{}, error) {
	/*
	 * mit enrollment stages:
	 * 0 = enter kerberos username/password
	 * 1 = duo
	 */

	stageInterface, hasStage := params["stage"]
	if !hasStage {
		return nil, data.SchoolError{Code: "missing_params"}
	}

	stageFloat, ok := stageInterface.(float64)
	if !ok {
		return nil, data.SchoolError{Code: "invalid_params"}
	}

	stage := int(stageFloat)

	usernameRaw, ok := params["username"]
	passwordRaw, ok2 := params["password"]

	if !ok || !ok2 {
		return nil, data.SchoolError{Code: "missing_params"}
	}

	username, ok := usernameRaw.(string)
	password, ok2 := passwordRaw.(string)

	if !ok || !ok2 || username == "" || password == "" {
		return nil, data.SchoolError{Code: "invalid_params"}
	}

	if stage < 0 || stage > 2 {
		// ???
		return nil, data.SchoolError{Code: "invalid_params"}
	}

	tsClient := touchstone.NewClient()

	challenge, err := tsClient.BeginUsernamePasswordAuth(username, password)
	if err != nil {
		if err == touchstone.ErrBadCreds {
			return nil, data.SchoolError{Code: "creds_incorrect"}
		}

		return nil, err
	}

	if stage == 0 {
		return nil, data.DetailedSchoolError{
			Code: "more_info",
			Details: map[string]interface{}{
				"duo": map[string]interface{}{
					"devices": challenge.Devices,
					"methods": challenge.Methods,
				},
			},
		}
	}

	duoMethodIndexInterface, hasStage := params["duoMethodIndex"]
	if !hasStage {
		return nil, data.SchoolError{Code: "missing_params"}
	}

	duoMethodIndexString, ok := duoMethodIndexInterface.(float64)
	if !ok {
		return nil, data.SchoolError{Code: "invalid_params"}
	}

	duoMethodIndex := int(duoMethodIndexString)

	if duoMethodIndex < 0 {
		return nil, data.SchoolError{Code: "invalid_params"}
	}

	if duoMethodIndex > len(challenge.Methods)-1 {
		return nil, data.SchoolError{Code: "invalid_params"}
	}

	duoMethod := challenge.Methods[duoMethodIndex]

	result, err := challenge.StartMethod(&duoMethod)
	if err != nil {
		return nil, err
	}

	if result.StatusCode != "pushed" {
		return nil, data.SchoolError{Code: "duo_denied"}
	}

	final, response, err := challenge.WaitForCompletion()
	if err != nil {
		return nil, err
	}

	if response.StatusCode != "allow" {
		return nil, data.SchoolError{Code: "duo_denied"}
	}

	// we made it!
	err = tsClient.CompleteAuthWithDuo(final)
	if err != nil {
		return nil, err
	}

	academicProfile, registration, peInfo, err := fetchDataWithClient(tsClient, username)
	if err != nil {
		return nil, err
	}

	// now we save the user's classes
	// wipe whatever's there
	err = clearUserData(tx, user)
	if err != nil {
		return nil, err
	}

	classInsertStmt, err := tx.Prepare("INSERT INTO mit_classes(subjectID, sectionID, title, units, userId) VALUES(?, ?, ?, ?, ?)")
	if err != nil {
		return nil, err
	}
	defer classInsertStmt.Close()
	for _, subject := range registration.StatusOfRegistration.Subjects {
		selection := subject.Selection
		_, err = classInsertStmt.Exec(
			strings.TrimSpace(selection.SubjectID),
			strings.TrimSpace(selection.SectionID),
			strings.TrimSpace(selection.Title),
			selection.Units,
			user.ID,
		)
		if err != nil {
			return nil, err
		}
	}

	var peInfoStringPointer *string

	if peInfo != nil {
		peInfoBytes, err := json.Marshal(peInfo)
		if err != nil {
			return nil, err
		}

		peInfoString := string(peInfoBytes)
		peInfoStringPointer = &peInfoString
	}

	return map[string]interface{}{
		"status":          1,
		"name":            academicProfile.Name,
		"username":        username,
		"year":            academicProfile.Year,
		"mitID":           academicProfile.MITID,
		"load":            registration.StatusOfRegistration.RegistrationLoad,
		"termCode":        registration.StatusOfRegistration.TermCode,
		"termDescription": registration.StatusOfRegistration.TermDescription,
		"peInfo":          peInfoStringPointer,
	}, nil
}

func (s *school) Unenroll(tx *sql.Tx, user *data.User) error {
	return clearUserData(tx, user)
}

func (s *school) NeedsUpdate(db *sql.DB) (bool, error) {
	return (s.importStatus != schools.ImportStatusOK), nil
}
<commit_msg>fix importing mit classes for a student<commit_after>package mit

import (
	"database/sql"
	"encoding/json"
	"strings"

	"github.com/thatoddmailbox/touchstone-client/touchstone"

	"github.com/MyHomeworkSpace/api-server/data"
	"github.com/MyHomeworkSpace/api-server/schools"
)

func clearUserData(tx *sql.Tx, user *data.User) error {
	// clear away anything that is in the db
	_, err := tx.Exec("DELETE FROM mit_classes WHERE userId = ?", user.ID)
	if err != nil {
		return err
	}

	return nil
}

func (s *school) Enroll(tx *sql.Tx, user *data.User, params map[string]interface{}) (map[string]interface{}, error) {
	/*
	 * mit enrollment stages:
	 * 0 = enter kerberos username/password
	 * 1 = duo
	 */

	stageInterface, hasStage := params["stage"]
	if !hasStage {
		return nil, data.SchoolError{Code: "missing_params"}
	}

	stageFloat, ok := stageInterface.(float64)
	if !ok {
		return nil, data.SchoolError{Code: "invalid_params"}
	}

	stage := int(stageFloat)

	usernameRaw, ok := params["username"]
	passwordRaw, ok2 := params["password"]

	if !ok || !ok2 {
		return nil, data.SchoolError{Code: "missing_params"}
	}

	username, ok := usernameRaw.(string)
	password, ok2 := passwordRaw.(string)

	if !ok || !ok2 || username == "" || password == "" {
		return nil, data.SchoolError{Code: "invalid_params"}
	}

	if stage < 0 || stage > 2 {
		// ???
		return nil, data.SchoolError{Code: "invalid_params"}
	}

	tsClient := touchstone.NewClient()

	challenge, err := tsClient.BeginUsernamePasswordAuth(username, password)
	if err != nil {
		if err == touchstone.ErrBadCreds {
			return nil, data.SchoolError{Code: "creds_incorrect"}
		}

		return nil, err
	}

	if stage == 0 {
		return nil, data.DetailedSchoolError{
			Code: "more_info",
			Details: map[string]interface{}{
				"duo": map[string]interface{}{
					"devices": challenge.Devices,
					"methods": challenge.Methods,
				},
			},
		}
	}

	duoMethodIndexInterface, hasStage := params["duoMethodIndex"]
	if !hasStage {
		return nil, data.SchoolError{Code: "missing_params"}
	}

	duoMethodIndexString, ok := duoMethodIndexInterface.(float64)
	if !ok {
		return nil, data.SchoolError{Code: "invalid_params"}
	}

	duoMethodIndex := int(duoMethodIndexString)

	if duoMethodIndex < 0 {
		return nil, data.SchoolError{Code: "invalid_params"}
	}

	if duoMethodIndex > len(challenge.Methods)-1 {
		return nil, data.SchoolError{Code: "invalid_params"}
	}

	duoMethod := challenge.Methods[duoMethodIndex]

	result, err := challenge.StartMethod(&duoMethod)
	if err != nil {
		return nil, err
	}

	if result.StatusCode != "pushed" {
		return nil, data.SchoolError{Code: "duo_denied"}
	}

	final, response, err := challenge.WaitForCompletion()
	if err != nil {
		return nil, err
	}

	if response.StatusCode != "allow" {
		return nil, data.SchoolError{Code: "duo_denied"}
	}

	// we made it!
	err = tsClient.CompleteAuthWithDuo(final)
	if err != nil {
		return nil, err
	}

	academicProfile, registration, peInfo, err := fetchDataWithClient(tsClient, username)
	if err != nil {
		return nil, err
	}

	// now we save the user's classes
	// wipe whatever's there
	err = clearUserData(tx, user)
	if err != nil {
		return nil, err
	}

	classInsertStmt, err := tx.Prepare("INSERT INTO mit_classes(subjectID, sectionID, title, units, sections, userID) VALUES(?, ?, ?, ?, '', ?)")
	if err != nil {
		return nil, err
	}
	defer classInsertStmt.Close()
	for _, subject := range registration.StatusOfRegistration.Subjects {
		selection := subject.Selection
		_, err = classInsertStmt.Exec(
			strings.TrimSpace(selection.SubjectID),
			strings.TrimSpace(selection.SectionID),
			strings.TrimSpace(selection.Title),
			selection.Units,
			user.ID,
		)
		if err != nil {
			return nil, err
		}
	}

	var peInfoStringPointer *string

	if peInfo != nil {
		peInfoBytes, err := json.Marshal(peInfo)
		if err != nil {
			return nil, err
		}

		peInfoString := string(peInfoBytes)
		peInfoStringPointer = &peInfoString
	}

	return map[string]interface{}{
		"status":          1,
		"name":            academicProfile.Name,
		"username":        username,
		"year":            academicProfile.Year,
		"mitID":           academicProfile.MITID,
		"load":            registration.StatusOfRegistration.RegistrationLoad,
		"termCode":        registration.StatusOfRegistration.TermCode,
		"termDescription": registration.StatusOfRegistration.TermDescription,
		"peInfo":          peInfoStringPointer,
	}, nil
}

func (s *school) Unenroll(tx *sql.Tx, user *data.User) error {
	return clearUserData(tx, user)
}

func (s *school) NeedsUpdate(db *sql.DB) (bool, error) {
	return (s.importStatus != schools.ImportStatusOK), nil
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Waiting for FDs via epoll(7).

package net

import (
	"os"
	"syscall"
)

const (
	readFlags  = syscall.EPOLLIN | syscall.EPOLLRDHUP
	writeFlags = syscall.EPOLLOUT
)

type pollster struct {
	epfd int

	// Events we're already waiting for
	// Must hold pollServer lock
	events map[int]uint32

	// An event buffer for EpollWait.
	// Used without a lock, may only be used by WaitFD.
	waitEventBuf [10]syscall.EpollEvent
	waitEvents   []syscall.EpollEvent

	// An event buffer for EpollCtl, to avoid a malloc.
	// Must hold pollServer lock.
	ctlEvent syscall.EpollEvent
}

func newpollster() (p *pollster, err error) {
	p = new(pollster)
	var e int

	// The arg to epoll_create is a hint to the kernel
	// about the number of FDs we will care about.
	// We don't know, and since 2.6.8 the kernel ignores it anyhow.
	if p.epfd, e = syscall.EpollCreate(16); e != 0 {
		return nil, os.NewSyscallError("epoll_create", e)
	}
	p.events = make(map[int]uint32)
	return p, nil
}

func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
	// pollServer is locked.

	var already bool
	p.ctlEvent.Fd = int32(fd)
	p.ctlEvent.Events, already = p.events[fd]
	if !repeat {
		p.ctlEvent.Events |= syscall.EPOLLONESHOT
	}
	if mode == 'r' {
		p.ctlEvent.Events |= readFlags
	} else {
		p.ctlEvent.Events |= writeFlags
	}

	var op int
	if already {
		op = syscall.EPOLL_CTL_MOD
	} else {
		op = syscall.EPOLL_CTL_ADD
	}
	if e := syscall.EpollCtl(p.epfd, op, fd, &p.ctlEvent); e != 0 {
		return false, os.NewSyscallError("epoll_ctl", e)
	}
	p.events[fd] = p.ctlEvent.Events
	return false, nil
}

func (p *pollster) StopWaiting(fd int, bits uint) {
	// pollServer is locked.

	events, already := p.events[fd]
	if !already {
		print("Epoll unexpected fd=", fd, "\n")
		return
	}

	// If syscall.EPOLLONESHOT is not set, the wait
	// is a repeating wait, so don't change it.
	if events&syscall.EPOLLONESHOT == 0 {
		return
	}

	// Disable the given bits.
	// If we're still waiting for other events, modify the fd
	// event in the kernel.  Otherwise, delete it.
	events &= ^uint32(bits)
	if int32(events)&^syscall.EPOLLONESHOT != 0 {
		p.ctlEvent.Fd = int32(fd)
		p.ctlEvent.Events = events
		if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_MOD, fd, &p.ctlEvent); e != 0 {
			print("Epoll modify fd=", fd, ": ", os.Errno(e).String(), "\n")
		}
		p.events[fd] = events
	} else {
		if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_DEL, fd, nil); e != 0 {
			print("Epoll delete fd=", fd, ": ", os.Errno(e).String(), "\n")
		}
		delete(p.events, fd)
	}
}

func (p *pollster) DelFD(fd int, mode int) {
	// pollServer is locked.

	if mode == 'r' {
		p.StopWaiting(fd, readFlags)
	} else {
		p.StopWaiting(fd, writeFlags)
	}

	// Discard any queued up events.
	i := 0
	for i < len(p.waitEvents) {
		if fd == int(p.waitEvents[i].Fd) {
			copy(p.waitEvents[i:], p.waitEvents[i+1:])
			p.waitEvents = p.waitEvents[:len(p.waitEvents)-1]
		} else {
			i++
		}
	}
}

func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
	for len(p.waitEvents) == 0 {
		var msec int = -1
		if nsec > 0 {
			msec = int((nsec + 1e6 - 1) / 1e6)
		}

		s.Unlock()
		n, e := syscall.EpollWait(p.epfd, p.waitEventBuf[0:], msec)
		s.Lock()

		if e != 0 {
			if e == syscall.EAGAIN || e == syscall.EINTR {
				continue
			}
			return -1, 0, os.NewSyscallError("epoll_wait", e)
		}
		if n == 0 {
			return -1, 0, nil
		}
		p.waitEvents = p.waitEventBuf[0:n]
	}

	ev := &p.waitEvents[0]
	p.waitEvents = p.waitEvents[1:]

	fd = int(ev.Fd)

	if ev.Events&writeFlags != 0 {
		p.StopWaiting(fd, writeFlags)
		return fd, 'w', nil
	}
	if ev.Events&readFlags != 0 {
		p.StopWaiting(fd, readFlags)
		return fd, 'r', nil
	}

	// Other events are error conditions - wake whoever is waiting.
	events, _ := p.events[fd]
	if events&writeFlags != 0 {
		p.StopWaiting(fd, writeFlags)
		return fd, 'w', nil
	}
	p.StopWaiting(fd, readFlags)
	return fd, 'r', nil
}

func (p *pollster) Close() error {
	return os.NewSyscallError("close", syscall.Close(p.epfd))
}
<commit_msg>net: update for error (linux)<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Waiting for FDs via epoll(7).

package net

import (
	"os"
	"syscall"
)

const (
	readFlags  = syscall.EPOLLIN | syscall.EPOLLRDHUP
	writeFlags = syscall.EPOLLOUT
)

type pollster struct {
	epfd int

	// Events we're already waiting for
	// Must hold pollServer lock
	events map[int]uint32

	// An event buffer for EpollWait.
	// Used without a lock, may only be used by WaitFD.
	waitEventBuf [10]syscall.EpollEvent
	waitEvents   []syscall.EpollEvent

	// An event buffer for EpollCtl, to avoid a malloc.
	// Must hold pollServer lock.
	ctlEvent syscall.EpollEvent
}

func newpollster() (p *pollster, err error) {
	p = new(pollster)
	var e int

	// The arg to epoll_create is a hint to the kernel
	// about the number of FDs we will care about.
	// We don't know, and since 2.6.8 the kernel ignores it anyhow.
	if p.epfd, e = syscall.EpollCreate(16); e != 0 {
		return nil, os.NewSyscallError("epoll_create", e)
	}
	p.events = make(map[int]uint32)
	return p, nil
}

func (p *pollster) AddFD(fd int, mode int, repeat bool) (bool, error) {
	// pollServer is locked.

	var already bool
	p.ctlEvent.Fd = int32(fd)
	p.ctlEvent.Events, already = p.events[fd]
	if !repeat {
		p.ctlEvent.Events |= syscall.EPOLLONESHOT
	}
	if mode == 'r' {
		p.ctlEvent.Events |= readFlags
	} else {
		p.ctlEvent.Events |= writeFlags
	}

	var op int
	if already {
		op = syscall.EPOLL_CTL_MOD
	} else {
		op = syscall.EPOLL_CTL_ADD
	}
	if e := syscall.EpollCtl(p.epfd, op, fd, &p.ctlEvent); e != 0 {
		return false, os.NewSyscallError("epoll_ctl", e)
	}
	p.events[fd] = p.ctlEvent.Events
	return false, nil
}

func (p *pollster) StopWaiting(fd int, bits uint) {
	// pollServer is locked.

	events, already := p.events[fd]
	if !already {
		print("Epoll unexpected fd=", fd, "\n")
		return
	}

	// If syscall.EPOLLONESHOT is not set, the wait
	// is a repeating wait, so don't change it.
	if events&syscall.EPOLLONESHOT == 0 {
		return
	}

	// Disable the given bits.
	// If we're still waiting for other events, modify the fd
	// event in the kernel.  Otherwise, delete it.
	events &= ^uint32(bits)
	if int32(events)&^syscall.EPOLLONESHOT != 0 {
		p.ctlEvent.Fd = int32(fd)
		p.ctlEvent.Events = events
		if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_MOD, fd, &p.ctlEvent); e != 0 {
			print("Epoll modify fd=", fd, ": ", os.Errno(e).Error(), "\n")
		}
		p.events[fd] = events
	} else {
		if e := syscall.EpollCtl(p.epfd, syscall.EPOLL_CTL_DEL, fd, nil); e != 0 {
			print("Epoll delete fd=", fd, ": ", os.Errno(e).Error(), "\n")
		}
		delete(p.events, fd)
	}
}

func (p *pollster) DelFD(fd int, mode int) {
	// pollServer is locked.

	if mode == 'r' {
		p.StopWaiting(fd, readFlags)
	} else {
		p.StopWaiting(fd, writeFlags)
	}

	// Discard any queued up events.
	i := 0
	for i < len(p.waitEvents) {
		if fd == int(p.waitEvents[i].Fd) {
			copy(p.waitEvents[i:], p.waitEvents[i+1:])
			p.waitEvents = p.waitEvents[:len(p.waitEvents)-1]
		} else {
			i++
		}
	}
}

func (p *pollster) WaitFD(s *pollServer, nsec int64) (fd int, mode int, err error) {
	for len(p.waitEvents) == 0 {
		var msec int = -1
		if nsec > 0 {
			msec = int((nsec + 1e6 - 1) / 1e6)
		}

		s.Unlock()
		n, e := syscall.EpollWait(p.epfd, p.waitEventBuf[0:], msec)
		s.Lock()

		if e != 0 {
			if e == syscall.EAGAIN || e == syscall.EINTR {
				continue
			}
			return -1, 0, os.NewSyscallError("epoll_wait", e)
		}
		if n == 0 {
			return -1, 0, nil
		}
		p.waitEvents = p.waitEventBuf[0:n]
	}

	ev := &p.waitEvents[0]
	p.waitEvents = p.waitEvents[1:]

	fd = int(ev.Fd)

	if ev.Events&writeFlags != 0 {
		p.StopWaiting(fd, writeFlags)
		return fd, 'w', nil
	}
	if ev.Events&readFlags != 0 {
		p.StopWaiting(fd, readFlags)
		return fd, 'r', nil
	}

	// Other events are error conditions - wake whoever is waiting.
	events, _ := p.events[fd]
	if events&writeFlags != 0 {
		p.StopWaiting(fd, writeFlags)
		return fd, 'w', nil
	}
	p.StopWaiting(fd, readFlags)
	return fd, 'r', nil
}

func (p *pollster) Close() error {
	return os.NewSyscallError("close", syscall.Close(p.epfd))
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package os_test

import (
	. "os"
	"testing"
	"syscall"
)

func TestMkdirAll(t *testing.T) {
	// Create new dir, in _obj so it will get
	// cleaned up by make if not by us.
	path := "_obj/_TestMkdirAll_/dir/./dir2"
	err := MkdirAll(path, 0777)
	if err != nil {
		t.Fatalf("MkdirAll %q: %s", path, err)
	}

	// Already exists, should succeed.
	err = MkdirAll(path, 0777)
	if err != nil {
		t.Fatalf("MkdirAll %q (second time): %s", path, err)
	}

	// Make file.
	fpath := path + "/file"
	_, err = Open(fpath, O_WRONLY|O_CREAT, 0666)
	if err != nil {
		t.Fatalf("create %q: %s", fpath, err)
	}

	// Can't make directory named after file.
	err = MkdirAll(fpath, 0777)
	if err == nil {
		t.Fatalf("MkdirAll %q: no error", fpath)
	}
	perr, ok := err.(*PathError)
	if !ok {
		t.Fatalf("MkdirAll %q returned %T, not *PathError", fpath, err)
	}
	if perr.Path != fpath {
		t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", fpath, perr.Path, fpath)
	}

	// Can't make subdirectory of file.
	ffpath := fpath + "/subdir"
	err = MkdirAll(ffpath, 0777)
	if err == nil {
		t.Fatalf("MkdirAll %q: no error", ffpath)
	}
	perr, ok = err.(*PathError)
	if !ok {
		t.Fatalf("MkdirAll %q returned %T, not *PathError", ffpath, err)
	}
	if perr.Path != fpath {
		t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", ffpath, perr.Path, fpath)
	}

	RemoveAll("_obj/_TestMkdirAll_")
}

func TestRemoveAll(t *testing.T) {
	// Work directory.
	path := "_obj/_TestRemoveAll_"
	fpath := path + "/file"
	dpath := path + "/dir"

	// Make directory with 1 file and remove.
	if err := MkdirAll(path, 0777); err != nil {
		t.Fatalf("MkdirAll %q: %s", path, err)
	}
	fd, err := Open(fpath, O_WRONLY|O_CREAT, 0666)
	if err != nil {
		t.Fatalf("create %q: %s", fpath, err)
	}
	fd.Close()
	if err = RemoveAll(path); err != nil {
		t.Fatalf("RemoveAll %q (first): %s", path, err)
	}
	if _, err := Lstat(path); err == nil {
		t.Fatalf("Lstat %q succeeded after RemoveAll (first)", path)
	}

	// Make directory with file and subdirectory and remove.
	if err = MkdirAll(dpath, 0777); err != nil {
		t.Fatalf("MkdirAll %q: %s", dpath, err)
	}
	fd, err = Open(fpath, O_WRONLY|O_CREAT, 0666)
	if err != nil {
		t.Fatalf("create %q: %s", fpath, err)
	}
	fd.Close()
	fd, err = Open(dpath+"/file", O_WRONLY|O_CREAT, 0666)
	if err != nil {
		t.Fatalf("create %q: %s", fpath, err)
	}
	fd.Close()
	if err = RemoveAll(path); err != nil {
		t.Fatalf("RemoveAll %q (second): %s", path, err)
	}
	if _, err := Lstat(path); err == nil {
		t.Fatalf("Lstat %q succeeded after RemoveAll (second)", path)
	}

	// Determine if we should run the following test.
	testit := true
	if syscall.OS == "windows" {
		// Chmod is not supported under windows.
		testit = false
	} else {
		// Test fails as root.
		testit = Getuid() != 0
	}
	if testit {
		// Make directory with file and subdirectory and trigger error.
		if err = MkdirAll(dpath, 0777); err != nil {
			t.Fatalf("MkdirAll %q: %s", dpath, err)
		}

		for _, s := range []string{fpath, dpath + "/file1", path + "/zzz"} {
			fd, err = Open(s, O_WRONLY|O_CREAT, 0666)
			if err != nil {
				t.Fatalf("create %q: %s", s, err)
			}
			fd.Close()
		}
		if err = Chmod(dpath, 0); err != nil {
			t.Fatalf("Chmod %q 0: %s", dpath, err)
		}
		if err = RemoveAll(path); err == nil {
			_, err := Lstat(path)
			if err == nil {
				t.Errorf("Can lstat %q after supposed RemoveAll", path)
			}
			t.Fatalf("RemoveAll %q succeeded with chmod 0 subdirectory: err %s", path, err)
		}
		perr, ok := err.(*PathError)
		if !ok {
			t.Fatalf("RemoveAll %q returned %T not *PathError", path, err)
		}
		if perr.Path != dpath {
			t.Fatalf("RemoveAll %q failed at %q not %q", path, perr.Path, dpath)
		}
		if err = Chmod(dpath, 0777); err != nil {
			t.Fatalf("Chmod %q 0777: %s", dpath, err)
		}
		for _, s := range []string{fpath, path + "/zzz"} {
			if _, err := Lstat(s); err == nil {
				t.Fatalf("Lstat %q succeeded after partial RemoveAll", s)
			}
		}
	}
	if err = RemoveAll(path); err != nil {
		t.Fatalf("RemoveAll %q after partial RemoveAll: %s", path, err)
	}
	if _, err := Lstat(path); err == nil {
		t.Fatalf("Lstat %q succeeded after RemoveAll (final)", path)
	}
}
<commit_msg>os: fix test of RemoveAll<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package os_test

import (
	. "os"
	"testing"
	"syscall"
)

func TestMkdirAll(t *testing.T) {
	// Create new dir, in _obj so it will get
	// cleaned up by make if not by us.
	path := "_obj/_TestMkdirAll_/dir/./dir2"
	err := MkdirAll(path, 0777)
	if err != nil {
		t.Fatalf("MkdirAll %q: %s", path, err)
	}

	// Already exists, should succeed.
	err = MkdirAll(path, 0777)
	if err != nil {
		t.Fatalf("MkdirAll %q (second time): %s", path, err)
	}

	// Make file.
	fpath := path + "/file"
	_, err = Open(fpath, O_WRONLY|O_CREAT, 0666)
	if err != nil {
		t.Fatalf("create %q: %s", fpath, err)
	}

	// Can't make directory named after file.
	err = MkdirAll(fpath, 0777)
	if err == nil {
		t.Fatalf("MkdirAll %q: no error", fpath)
	}
	perr, ok := err.(*PathError)
	if !ok {
		t.Fatalf("MkdirAll %q returned %T, not *PathError", fpath, err)
	}
	if perr.Path != fpath {
		t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", fpath, perr.Path, fpath)
	}

	// Can't make subdirectory of file.
	ffpath := fpath + "/subdir"
	err = MkdirAll(ffpath, 0777)
	if err == nil {
		t.Fatalf("MkdirAll %q: no error", ffpath)
	}
	perr, ok = err.(*PathError)
	if !ok {
		t.Fatalf("MkdirAll %q returned %T, not *PathError", ffpath, err)
	}
	if perr.Path != fpath {
		t.Fatalf("MkdirAll %q returned wrong error path: %q not %q", ffpath, perr.Path, fpath)
	}

	RemoveAll("_obj/_TestMkdirAll_")
}

func TestRemoveAll(t *testing.T) {
	// Work directory.
	path := "_obj/_TestRemoveAll_"
	fpath := path + "/file"
	dpath := path + "/dir"

	// Make directory with 1 file and remove.
	if err := MkdirAll(path, 0777); err != nil {
		t.Fatalf("MkdirAll %q: %s", path, err)
	}
	fd, err := Open(fpath, O_WRONLY|O_CREAT, 0666)
	if err != nil {
		t.Fatalf("create %q: %s", fpath, err)
	}
	fd.Close()
	if err = RemoveAll(path); err != nil {
		t.Fatalf("RemoveAll %q (first): %s", path, err)
	}
	if _, err := Lstat(path); err == nil {
		t.Fatalf("Lstat %q succeeded after RemoveAll (first)", path)
	}

	// Make directory with file and subdirectory and remove.
	if err = MkdirAll(dpath, 0777); err != nil {
		t.Fatalf("MkdirAll %q: %s", dpath, err)
	}
	fd, err = Open(fpath, O_WRONLY|O_CREAT, 0666)
	if err != nil {
		t.Fatalf("create %q: %s", fpath, err)
	}
	fd.Close()
	fd, err = Open(dpath+"/file", O_WRONLY|O_CREAT, 0666)
	if err != nil {
		t.Fatalf("create %q: %s", fpath, err)
	}
	fd.Close()
	if err = RemoveAll(path); err != nil {
		t.Fatalf("RemoveAll %q (second): %s", path, err)
	}
	if _, err := Lstat(path); err == nil {
		t.Fatalf("Lstat %q succeeded after RemoveAll (second)", path)
	}

	// Determine if we should run the following test.
	testit := true
	if syscall.OS == "windows" {
		// Chmod is not supported under windows.
		testit = false
	} else {
		// Test fails as root.
		testit = Getuid() != 0
	}
	if testit {
		// Make directory with file and subdirectory and trigger error.
		if err = MkdirAll(dpath, 0777); err != nil {
			t.Fatalf("MkdirAll %q: %s", dpath, err)
		}

		for _, s := range []string{fpath, dpath + "/file1", path + "/zzz"} {
			fd, err = Open(s, O_WRONLY|O_CREAT, 0666)
			if err != nil {
				t.Fatalf("create %q: %s", s, err)
			}
			fd.Close()
		}
		if err = Chmod(dpath, 0); err != nil {
			t.Fatalf("Chmod %q 0: %s", dpath, err)
		}

		// No error checking here: either RemoveAll
		// will or won't be able to remove dpath;
		// either way we want to see if it removes fpath
		// and path/zzz.  Reasons why RemoveAll might
		// succeed in removing dpath as well include:
		//	* running as root
		//	* running on a file system without permissions (FAT)
		RemoveAll(path)
		Chmod(dpath, 0777)

		for _, s := range []string{fpath, path + "/zzz"} {
			if _, err := Lstat(s); err == nil {
				t.Fatalf("Lstat %q succeeded after partial RemoveAll", s)
			}
		}
	}
	if err = RemoveAll(path); err != nil {
		t.Fatalf("RemoveAll %q after partial RemoveAll: %s", path, err)
	}
	if _, err := Lstat(path); err == nil {
		t.Fatalf("Lstat %q succeeded after RemoveAll (final)", path)
	}
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Time-related runtime and pieces of package time.

package runtime

import "unsafe"

// Package time knows the layout of this structure.
// If this struct changes, adjust ../time/sleep.go:/runtimeTimer and netpoll.goc:/timer.
// For GOOS=nacl, package syscall knows the layout of this structure.
// If this struct changes, adjust ../syscall/net_nacl.go:/runtimeTimer.
type timer struct {
	i int // heap index

	// Timer wakes up at when, and then at when+period, ... (period > 0 only)
	// each time calling f(now, arg) in the timer goroutine, so f must be
	// a well-behaved function and not block.
	when   int64
	period int64
	f      func(interface{})
	arg    interface{}
}

var timers struct {
	lock         lock
	gp           *g
	created      bool
	sleeping     bool
	rescheduling bool
	waitnote     note
	t            []*timer
}

// Package time APIs.
// Godoc uses the comments in package time, not these.

// time.now is implemented in assembly.

// Sleep puts the current goroutine to sleep for at least ns nanoseconds.
func timeSleep(ns int64) {
	if ns <= 0 {
		return
	}

	t := new(timer)
	t.when = gonanotime() + ns
	t.f = goroutineReady
	t.arg = getg()
	golock(&timers.lock)
	addtimerLocked(t)
	goparkunlock(&timers.lock, "sleep")
}

// startTimer adds t to the timer heap.
func startTimer(t *timer) {
	if raceenabled {
		racerelease(unsafe.Pointer(t))
	}
	addtimer(t)
}

// stopTimer removes t from the timer heap if it is there.
// It returns true if t was removed, false if t wasn't even there.
func stopTimer(t *timer) bool {
	return deltimer(t)
}

// Go runtime.

// Ready the goroutine arg.
func goroutineReady(arg interface{}) {
	goready(arg.(*g))
}

func addtimer(t *timer) {
	golock(&timers.lock)
	addtimerLocked(t)
	gounlock(&timers.lock)
}

// Add a timer to the heap and start or kick the timer proc.
// If the new timer is earlier than any of the others.
// Timers are locked.
func addtimerLocked(t *timer) {
	// when must never be negative; otherwise timerproc will overflow
	// during its delta calculation and never expire other runtime·timers.
	if t.when < 0 {
		t.when = 1<<63 - 1
	}
	t.i = len(timers.t)
	timers.t = append(timers.t, t)
	siftupTimer(t.i)
	if t.i == 0 {
		// siftup moved to top: new earliest deadline.
		if timers.sleeping {
			timers.sleeping = false
			gonotewakeup(&timers.waitnote)
		}
		if timers.rescheduling {
			timers.rescheduling = false
			goready(timers.gp)
		}
	}
	if !timers.created {
		timers.created = true
		go timerproc()
	}
}

// Delete timer t from the heap.
// Do not need to update the timerproc: if it wakes up early, no big deal.
func deltimer(t *timer) bool {
	// Dereference t so that any panic happens before the lock is held.
	// Discard result, because t might be moving in the heap.
	_ = t.i

	golock(&timers.lock)
	// t may not be registered anymore and may have
	// a bogus i (typically 0, if generated by Go).
	// Verify it before proceeding.
	i := t.i
	last := len(timers.t) - 1
	if i < 0 || i > last || timers.t[i] != t {
		gounlock(&timers.lock)
		return false
	}
	if i != last {
		timers.t[i] = timers.t[last]
		timers.t[i].i = i
	}
	timers.t[last] = nil
	timers.t = timers.t[:last]
	if i != last {
		siftupTimer(i)
		siftdownTimer(i)
	}
	gounlock(&timers.lock)
	return true
}

// Timerproc runs the time-driven events.
// It sleeps until the next event in the timers heap.
// If addtimer inserts a new earlier event, addtimer1 wakes timerproc early.
func timerproc() {
	timers.gp = getg()
	timers.gp.issystem = 1
	for {
		golock(&timers.lock)
		timers.sleeping = false
		now := gonanotime()
		delta := int64(-1)
		for {
			if len(timers.t) == 0 {
				delta = -1
				break
			}
			t := timers.t[0]
			delta = t.when - now
			if delta > 0 {
				break
			}
			if t.period > 0 {
				// leave in heap but adjust next time to fire
				t.when += t.period * (1 + -delta/t.period)
				siftdownTimer(0)
			} else {
				// remove from heap
				last := len(timers.t) - 1
				if last > 0 {
					timers.t[0] = timers.t[last]
					timers.t[0].i = 0
				}
				timers.t[last] = nil
				timers.t = timers.t[:last]
				if last > 0 {
					siftdownTimer(0)
				}
				t.i = -1 // mark as removed
			}
			f := t.f
			arg := t.arg
			gounlock(&timers.lock)
			if raceenabled {
				raceacquire(unsafe.Pointer(t))
			}
			f(arg)
			golock(&timers.lock)
		}
		if delta < 0 {
			// No timers left - put goroutine to sleep.
			timers.rescheduling = true
			goparkunlock(&timers.lock, "timer goroutine (idle)")
			continue
		}
		// At least one timer pending.  Sleep until then.
		timers.sleeping = true
		gonoteclear(&timers.waitnote)
		gounlock(&timers.lock)
		gonotetsleepg(&timers.waitnote, delta)
	}
}

// Heap maintenance algorithms.

func siftupTimer(i int) {
	t := timers.t
	when := t[i].when
	tmp := t[i]
	for i > 0 {
		p := (i - 1) / 4 // parent
		if when >= t[p].when {
			break
		}
		t[i] = t[p]
		t[i].i = i
		t[p] = tmp
		t[p].i = p
		i = p
	}
}

func siftdownTimer(i int) {
	t := timers.t
	n := len(t)
	when := t[i].when
	tmp := t[i]
	for {
		c := i*4 + 1 // left child
		c3 := c + 2  // mid child
		if c >= n {
			break
		}
		w := t[c].when
		if c+1 < n && t[c+1].when < w {
			w = t[c+1].when
			c++
		}
		if c3 < n {
			w3 := t[c3].when
			if c3+1 < n && t[c3+1].when < w3 {
				w3 = t[c3+1].when
				c3++
			}
			if w3 < w {
				w = w3
				c = c3
			}
		}
		if w >= when {
			break
		}
		t[i] = t[c]
		t[i].i = i
		t[c] = tmp
		t[c].i = c
		i = c
	}
}
<commit_msg>runtime: restore nacl timens Deleted in cl/123700044. I am not sure whether I need to restore it, or delete rest of the uses...<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Time-related runtime and pieces of package time.

package runtime

import "unsafe"

// Package time knows the layout of this structure.
// If this struct changes, adjust ../time/sleep.go:/runtimeTimer and netpoll.goc:/timer.
// For GOOS=nacl, package syscall knows the layout of this structure.
// If this struct changes, adjust ../syscall/net_nacl.go:/runtimeTimer.
type timer struct {
	i int // heap index

	// Timer wakes up at when, and then at when+period, ... (period > 0 only)
	// each time calling f(now, arg) in the timer goroutine, so f must be
	// a well-behaved function and not block.
	when   int64
	period int64
	f      func(interface{})
	arg    interface{}
}

var timers struct {
	lock         lock
	gp           *g
	created      bool
	sleeping     bool
	rescheduling bool
	waitnote     note
	t            []*timer
}

// nacl fake time support.
var timens int64

// Package time APIs.
// Godoc uses the comments in package time, not these.

// time.now is implemented in assembly.

// Sleep puts the current goroutine to sleep for at least ns nanoseconds.
func timeSleep(ns int64) {
	if ns <= 0 {
		return
	}

	t := new(timer)
	t.when = gonanotime() + ns
	t.f = goroutineReady
	t.arg = getg()
	golock(&timers.lock)
	addtimerLocked(t)
	goparkunlock(&timers.lock, "sleep")
}

// startTimer adds t to the timer heap.
func startTimer(t *timer) {
	if raceenabled {
		racerelease(unsafe.Pointer(t))
	}
	addtimer(t)
}

// stopTimer removes t from the timer heap if it is there.
// It returns true if t was removed, false if t wasn't even there.
func stopTimer(t *timer) bool {
	return deltimer(t)
}

// Go runtime.

// Ready the goroutine arg.
func goroutineReady(arg interface{}) {
	goready(arg.(*g))
}

func addtimer(t *timer) {
	golock(&timers.lock)
	addtimerLocked(t)
	gounlock(&timers.lock)
}

// Add a timer to the heap and start or kick the timer proc.
// If the new timer is earlier than any of the others.
// Timers are locked.
func addtimerLocked(t *timer) {
	// when must never be negative; otherwise timerproc will overflow
	// during its delta calculation and never expire other runtime·timers.
	if t.when < 0 {
		t.when = 1<<63 - 1
	}
	t.i = len(timers.t)
	timers.t = append(timers.t, t)
	siftupTimer(t.i)
	if t.i == 0 {
		// siftup moved to top: new earliest deadline.
		if timers.sleeping {
			timers.sleeping = false
			gonotewakeup(&timers.waitnote)
		}
		if timers.rescheduling {
			timers.rescheduling = false
			goready(timers.gp)
		}
	}
	if !timers.created {
		timers.created = true
		go timerproc()
	}
}

// Delete timer t from the heap.
// Do not need to update the timerproc: if it wakes up early, no big deal.
func deltimer(t *timer) bool {
	// Dereference t so that any panic happens before the lock is held.
	// Discard result, because t might be moving in the heap.
	_ = t.i

	golock(&timers.lock)
	// t may not be registered anymore and may have
	// a bogus i (typically 0, if generated by Go).
	// Verify it before proceeding.
	i := t.i
	last := len(timers.t) - 1
	if i < 0 || i > last || timers.t[i] != t {
		gounlock(&timers.lock)
		return false
	}
	if i != last {
		timers.t[i] = timers.t[last]
		timers.t[i].i = i
	}
	timers.t[last] = nil
	timers.t = timers.t[:last]
	if i != last {
		siftupTimer(i)
		siftdownTimer(i)
	}
	gounlock(&timers.lock)
	return true
}

// Timerproc runs the time-driven events.
// It sleeps until the next event in the timers heap.
// If addtimer inserts a new earlier event, addtimer1 wakes timerproc early.
func timerproc() {
	timers.gp = getg()
	timers.gp.issystem = 1
	for {
		golock(&timers.lock)
		timers.sleeping = false
		now := gonanotime()
		delta := int64(-1)
		for {
			if len(timers.t) == 0 {
				delta = -1
				break
			}
			t := timers.t[0]
			delta = t.when - now
			if delta > 0 {
				break
			}
			if t.period > 0 {
				// leave in heap but adjust next time to fire
				t.when += t.period * (1 + -delta/t.period)
				siftdownTimer(0)
			} else {
				// remove from heap
				last := len(timers.t) - 1
				if last > 0 {
					timers.t[0] = timers.t[last]
					timers.t[0].i = 0
				}
				timers.t[last] = nil
				timers.t = timers.t[:last]
				if last > 0 {
					siftdownTimer(0)
				}
				t.i = -1 // mark as removed
			}
			f := t.f
			arg := t.arg
			gounlock(&timers.lock)
			if raceenabled {
				raceacquire(unsafe.Pointer(t))
			}
			f(arg)
			golock(&timers.lock)
		}
		if delta < 0 {
			// No timers left - put goroutine to sleep.
			timers.rescheduling = true
			goparkunlock(&timers.lock, "timer goroutine (idle)")
			continue
		}
		// At least one timer pending.  Sleep until then.
		timers.sleeping = true
		gonoteclear(&timers.waitnote)
		gounlock(&timers.lock)
		gonotetsleepg(&timers.waitnote, delta)
	}
}

// Heap maintenance algorithms.

func siftupTimer(i int) {
	t := timers.t
	when := t[i].when
	tmp := t[i]
	for i > 0 {
		p := (i - 1) / 4 // parent
		if when >= t[p].when {
			break
		}
		t[i] = t[p]
		t[i].i = i
		t[p] = tmp
		t[p].i = p
		i = p
	}
}

func siftdownTimer(i int) {
	t := timers.t
	n := len(t)
	when := t[i].when
	tmp := t[i]
	for {
		c := i*4 + 1 // left child
		c3 := c + 2  // mid child
		if c >= n {
			break
		}
		w := t[c].when
		if c+1 < n && t[c+1].when < w {
			w = t[c+1].when
			c++
		}
		if c3 < n {
			w3 := t[c3].when
			if c3+1 < n && t[c3+1].when < w3 {
				w3 = t[c3+1].when
				c3++
			}
			if w3 < w {
				w = w3
				c = c3
			}
		}
		if w >= when {
			break
		}
		t[i] = t[c]
		t[i].i = i
		t[c] = tmp
		t[c].i = c
		i = c
	}
}
<|endoftext|>